今回は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.ステート名
でステートにアクセスできます。
補足2:
親コンポーネントのrender
にある<>〜</>
←「これ何?」 と思うかもしれませんが、これは「React Fragment」と呼ばれるものです。
通常renderでは要素を1つしか入れられないので全体を<div>
で囲む必要がありますが、Fragmentを使えば全体を囲むdivなどを入れずにそのまま表示させることができます。
レンダリング後のコードを見ればわかりますが、<>〜</>
を使ったコンポーネントからはコンポーネントを囲む<div>
は出力されません。余計なタグを入れなくて済むというわけです。
参考>>フラグメント – React
まとめ
Reactで子コンポーネントから親コンポーネントのステートを操作する方法を紹介しました。
コンポーネントをまたいでステートやメソッドを操作したいことはよくあると思うので、試してみてください。