k01ken’s b10g

He110 W0r1d!

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に入れた時点で自動的に行ってくれるようだ。