Reactで詰まったポイントの解決メモ
開発環境は、Windows10 64bit(Pro) + react@16.8.6。
■ライフサイクルメソッドについて
・stateが変更されるたびに、componentWillUpdate,componentDidUpdateメソッドがそれぞれ呼び出される。
■componentWillMountを使用すると、querySelectorAllでは、まだ要素は読み込めない。componentDidMonutでようやく読み込める。
・イベントは、addEventListenerで追加するのではなくて、タグにonClickやonFocusなど書いて、その中にコールバック関数を指定する方法が一般的か。
■ルーティングで、ログインページとユーザーの個別ページの場合、LinkコンポーネントをSwitchコンポーネントで囲っておいて、ユーザーの個別ページを一番最後に設置しておかないと、BrowserRouterコンポーネントでは個別ページをログインページと認識して両方表示されてしまう。
<Switch> <Link to="/login" render={Login} /> <Link to="/:username" render={UserPage} /> </Switch>
Switchコンポーネントだと、一番最初にマッチしたものだけを表示してくれる。
参考リンク
React入門
■LinkコンポーネントでonClickメソッド属性にメソッドを指定していることで無限ループしてしまう際の対処法
例えば、バックエンド側からデータを引っ張ってくるメソッドをreadPageとして、下記のように記述すると、
<Link onClick={this.readPage('/')} to="/" />
無限ループしてしまう。(無限に指定ページを読み込もうとする)
括弧をつけて、記述しているから起動している?
ただ、
<Link onClick={() => { this.readPage('/')} } to="/" />
という風にアロー関数で指定すると大丈夫。
メソッドを最初からアロー関数で定義していたらどうなのだろうか?
■子コンポーネントから親コンポーネントのstateを変更する
stateを変更するメソッドは、コンストラクタでバインドしておくこと。
そうしないと、変更できない。
親コンポーネント側
constructor(props){ super(props); this.state = { isClicked: false }; this.clickStateChanger = this.clickStateChanger.bind(this); } clickStateChanger(){ let current_state = this.state.isClicked; this.setState({isClicked: !current_state}); console.log("current_state: " + !current_state); } <Child clickStateChanger={this.clickStateChanger} />
子コンポーネント側
<button onClick={this.props.clickStateChanger} >click me</button>
参考リンク
[react]子のコンポーネントから親のstateを変更する方法 - Qiita
コンポーネントに関数を渡す – React
■親コンポーネントから子コンポーネントへメソッドを渡して使用する際の注意点
親コンポーネントからメソッドを受け取って、子コンポーネントのbuttonのonClick属性などに設定して、呼び出すパターンです。
親コンポーネント側
handleAlert(){ console.log("handleAlert"); } <Child handleAlert={this.handleAlert} /> /* ここで、 <Child handleAlert={() => { this.handleAlert} } /> のようにアロー関数で渡すとhandleAlertが動作しないので注意。 */
子コンポーネント側
<button onClick={this.props.handleAlert}>click me</button>
これだと、問題なく呼び出せますが、例えば、子コンポーネント側で、メソッドを用意して、その中で、親コンポーネントのメソッドを呼び出したい場合は、子コンポーネント側を以下のようにすると、wrap()メソッド内の、thisが、親コンポーネントを指していなくて、TypeError: this is undefinedとなる。
子コンポーネント側
wrap(){ this.props.handleAlert(); } <button onClick={this.wrap}>click me</button>
そこで、wrap()メソッドをアロー関数として呼び出すと問題なく動作する。
子コンポーネント側
wrap = () => { this.props.handleAlert(); } <button onClick={this.wrap}>click me</button>
■子コンポーネントへメソッドを渡す際に、引数を指定できるようにする
親コンポーネント側
import React from 'react'; import Child from './Child'; class Parent extends React.Component{ testMethod(name){ console.log("Hello, " + name + "!"); } render(){ return( <Child testMethod={(name) => this.testMethod(name)} /> ); } }
子コンポーネント側
<button onClick={() => this.props.testMethod("k01ken")}>click me</button> export default Child;
参考リンク
React子コンポーネントから親の引数付きメソッドを実行する - Qiita
■JSX文法内部で条件分岐させる
JSX内にて、stateの状態によって、CSSのclass属性を切り替えたい場合は、
<div className={this.state.isClicked === true ? "isClicked" : "notClicked"}></div>
のように書いていきます。
他にも、一部の文字列は共通だが、残りの文字列は状態に応じて切り替えたい場合は、状態に応じて切り替わる方を()で括っておくこと。
例えば、アイコン画像がアップロードされていれば、アイコン画像を、なければ、デフォルトのアイコン画像を表示させたい場合は、
<img src={"/img/user_icon/" + (this.state.icon_image !== null ? "useruploadicon.jpg" : "defaulticon.jpg")} />
としておく。
もっと細かくネストしたい場合は、三項演算子をネストします。
<div> { this.state.isClicked === true ? this.state.isChecked === true ? クリックして、かつ、チェックしています : クリックしましたが、チェックはしてません : クリックしてません } </div>
参考リンク
React.jsの知っておいて損はないTips - Qiita
■class属性をタグ内に書く場合は、classNameと書くこと
<div class="test"></div>
じゃなくて、
<div className="test"></div>
という風にする。
■this.State内の配列の一部を変更する方法
constructor(props){ super(props); this.state = { frults: ["apple", "orange", "grape"] }; } fruits_change(){ var copy_fruits_array = this.state.fruits.slice(); copy_fruits_array[0] = 'banana'; this.setState({fruits: copy_fruits_array }); }
参考リンク
ReactのsetStateで配列の一部を変更する - Qiita
■this.state内にデータを入れると自動的にサニタイズしてくれる
例えば、チャット機能など作る際に、ユーザーが、
<script>alert("hello");</script>
などのプログラムを書くと、プログラムが実行してしまいhelloと書かれたalertが表示され、セキュリティ的に危険なので、普通だったら、HTMLサニタイズするプログラムを書かなくてはならないが、Reactの場合は、this.stateに入れた時点で自動的に行ってくれるようだ。