Reactで子コンポーネントから親のステートを操作する方法

JavaScript

今回はReactで子コンポーネントから親コンポーネントのステートを操作する方法を解説します。

サンプルとしてクリックした回数をカウントする処理をしてみます。クリックした回数は親コンポーネントのステートで管理し、子コンポーネントの処理でステートを操作します。

デモはこちら↓

デモ

スポンサーリンク

子コンポーネントから親コンポーネントのステートを操作する方法

デモのコードを解説していきます。

まずは子コンポーネント(<Child />)

export default class Child extends Component {
  render() {
    // propsでメソッドを渡す
    return <button onClick={this.props.onClick}>increment</button>;
  }
}

ボタンクリック時にonClickを実行するというものです。

propsで親から子にクリック時の処理を渡し、親でメソッドを書くことで親のステートを操作できるようにします。

 

続いて親コンポーネント(<Parent />)

export default class Parent extends Component {
  constructor(props) {
    super(props);
    // ステートを用意
    this.state = {
      count: 0,
    }
    this.handleClick = this.handleClick.bind(this);
  }

  // ステートを操作するメソッド
  handleClick() {
    this.setState(prevState => ({
      count: prevState.count + 1
    })); 
  }

  render() {
    return (
      <>
        <Child onClick={this.handleClick} />{/* ←onClickプロパティにメソッドを指定 */}
        {this.state.count}
      </>
    );
  }
}

propsで親から子にプロパティを渡しているので、あとは親で処理を書いて呼び出すだけです。

これでボタン(<Child />)をクリックした時に親(<Parent />)のステートを変更する処理ができました。

 

補足1:

親コンポーネントのメソッドを見て、ここ↓は

handleClick() {
   this.setState(prevState => ({
    count: prevState.count + 1
  })); 
}

こう↓じゃないの?

handleClick() {
  this.setState({
    count: this.state.count + 1
  });
}

と思う人もいるかもしれませんが、下のやり方は避けたほうがいいです。

理由はsetState内でthis.stateを参照すると古いステートが参照され、期待通りに値が変化しない可能性があるからです。上のやり方のように関数の形で処理すれば避けられるのでこっちを使いましょう。

なお関数の第一引数にprevStateを渡し、prevState.ステート名でステートにアクセスできます。

参考>>eslint-plugin-react/no-access-state-in-setstate

 

補足2:

親コンポーネントのrenderにある<>〜</>←「これ何?」 と思うかもしれませんが、これは「React Fragment」と呼ばれるものです。

通常renderでは要素を1つしか入れられないので全体を<div>で囲む必要がありますが、Fragmentを使えば全体を囲むdivなどを入れずにそのまま表示させることができます。

レンダリング後のコードを見ればわかりますが、<>〜</>を使ったコンポーネントからはコンポーネントを囲む<div>は出力されません。余計なタグを入れなくて済むというわけです。

参考>>フラグメント – React

 

まとめ

Reactで子コンポーネントから親コンポーネントのステートを操作する方法を紹介しました。

コンポーネントをまたいでステートやメソッドを操作したいことはよくあると思うので、試してみてください。