React では通常、親コンポーネントから子コンポーネントの値を引き渡すには props を通じて引き渡します。
子コンポーネントは渡されたその props を constructor で state などに保存して利用します。
実はこの値の受け渡しは「親→子」でしか利用できず「子→親」の値の受け渡しは props を通じては行えません。
(子コンポーネントでは親から渡された props はリードオンリーです。)
でもどうしても子コンポーネントから親コンポーネントの値(State)を変更したい場合があります。
そんな時はどうすればよいのかをこの記事では解説します。
React 環境の作成方法は以下のサイトを参照して作成してください。
Reactで親から子の値(State)を変更する
React ではコンポーネント間の値の受け渡しは props を用いて「親コンポーネント→子コンポーネント」へ渡します。
まずは、親コンポーネントのソースです。
import React from "react" ; import Child from "./Child" ; export default class Parent extends React.Component { constructor( props ){ super( props ) ; this.state ={ count : 0 } ; this.countUp = this.countUp.bind(this); } countUp( flg ){ if( flg == "up" ){ this.setState( { count : this.state.count + 1 } ) ; } else{ this.setState( { count : this.state.count - 1 } ) ; } } render(){ return( <React.Fragment> <input type="button" value="カウントアップ" onClick={( event ) => { this.countUp( 'up' ) ; }} /> <input type="button" value="カウントダウン" onClick={( event ) => { this.countUp( 'down' ) ; }} /> <Child count={this.state.count} /> </React.Fragment> ) ; } }
次に子コンポーネントのソースです。
import React from "react" ; export default class Child extends React.Component { constructor( props ){ super( props ) ; this.state = { count : this.props.count, } ; } render(){ return( <React.Fragment> <div>count={this.state.count}</div> </React.Fragment> ); } componentDidUpdate( prevProps ){ if( prevProps.count != this.props.count ){ this.setState({ count : this.props.count } ); } } }
これで親コンポーネントのボタンをクリックすると連動して子コンポーネントで count の値を動的に変更することができます。
Reactで子から親の値(State)を変更する
React で子コンポーネントから親コンポーネントの値(State)を変更するには親コンポーネントを変更するコールバック関数作成し、その関数を子コンポーネントへ props を通じして渡して、子コンポーネント側でコールバック関数を適宜呼び出します。
まずは、親コンポーネントのソースです。
import React from "react" ; import Child from "./Child" ; export default class Parent extends React.Component { constructor( props ){ super( props ) ; this.state = { count : 0 } ; this.countUp = this.countUp.bind(this); } //stateのcountの値を更新するコールバック関数 countUp( flg ){ this.setState( { count : this.state.count + flg } ) ; } render(){ return( <React.Fragment> <div>count={this.state.count}</div> <Child callback={this.countUp} /> </React.Fragment> ) ; } }
上記のソースで countUp メソッドが子コンポーネント関数に引き渡すコールバック関数です。
次にコールバック関数を受け取る側の子コンポーネントのソースです。
import React from "react" ; export default class Child extends React.Component { constructor( props ){ super( props ) ; this.state = { callback : this.props.callback, } ; this.CallBackFunction = this.CallBackFunction.bind(this); } CallBackFunction( flg ){ if( flg == "up" ){ this.state.callback( 1 ) ; } else{ this.state.callback( -1 ) ; } } render(){ return( <React.Fragment> <input type="button" value="カウントアップ" onClick={( event ) => { this.CallBackFunction( 'up' ) ; }} /> <input type="button" value="カウントダウン" onClick={( event ) => { this.CallBackFunction( 'down' ) ; }} /> </React.Fragment> ); } }
子コンポーネント側で用意したカウントアップ、カウントダウンボタンのクリックイベントで親コンポーネントから渡されたコールバック関数を呼び出します。
こうすることで結果的に子コンポーネントから親コンポーネントの値(State)を変更することができるようになります。
まとめ
React で子コンポーネントから親コンポーネントの値(State)を変更するには親コンポーネントを変更するコールバック関数作成し、その関数を子コンポーネントへ props を通じして渡すことで、子コンポーネントから親コンポーネントの値(State)を変更することができます。