こんにちは。
React&ReduxによるSPA開発の業務に直近の約一年ほど関わっており、現在も継続中の者です。
ご質問に
以下のような
として挙げられているコードについては
- 子のイベントを介して親のステートを変更している。ただし、そのイベントは(例えば click のような)DOMイベントではなく、ライフサイクルイベントと呼ぶべきイベント
というのが回答になるかなと思います。以下、この回答について説明します。
ご質問のコードで、parentMethod
が使われているのは Child
の componentDidMount()
の中の、以下の部分
javascript
1componentDidMount() {
2 //getToken()は何かのトークンをとってくる関数と仮定
3 let token = getToken()
4 this.props.parentMethod(token);
5 }
ですが、これは
Child
コンポーネントは、自身がマウントされたというイベントを契機に、Parent
からpropsで渡される parentMethod
を呼び出す。
と言えて、parentMethod
は Parentのstateを変えるので、上記は「子のイベントを介して」親のステートを変更するコードとなっています。
componentDidMount()
はライフサイクルメソッドのひとつですが、これを「コンポーネントがマウントされたというイベントによって呼ばれるメソッド」というように、イベントという言葉を使って理解しておくことが間違いではないということの根拠となる記事を挙げます。
上記は、Twitterのフォロワー数約2万の技術メンター Tyler McGinnis さんによる投稿ですが、タイトルにあるとおり、"Life Cycle Events" と、イベントという言葉を使っています。
この "ライフサイクルイベント" という言葉を借りれば、
- 何らかの要素がクリックされたというイベントは DOMイベント 。コンポーネントがマウントされたというイベントはライフサイクルイベント。どちらもイベントであることには変わりない。従って、Parent は Children で発生したイベントによって、stateを変更される。
と、状況を整理することができます。
実際のコードで確認してみますと、以下はReactNativeアプリではなく、Webアプリを作る react-create-app で
作成される App.js を Parent.js にして、ご質問に挙げられているコードに、console.log 出力を何点か加えたものです。
index.js
javascript
1import React from 'react';
2import ReactDOM from 'react-dom';
3import Parent from './Parent';
4
5ReactDOM.render(<Parent />, document.getElementById('root'));
Parent.js
javascript
1import React, { Component } from 'react';
2
3class Parent extends Component {
4
5 constructor(props) {
6 super(props);
7 this.state = {
8 token: null
9 };
10 this.renderingCount = 0;
11 }
12
13 updateState(token){
14 console.log('Parent#updateState: token=' + token);
15 this.setState({token});
16 }
17
18 render() {
19 this.renderingCount ++;
20 console.log(`renderingCount: ${this.renderingCount}`);
21 console.log(this.state);
22 return (
23 <Child parentMethod={token => this.updateState(token)} />
24 );
25 }
26}
27
28class Child extends Component {
29
30 componentDidMount() {
31 //getToken()は何かのトークンをとってくる関数と仮定
32 //let token = getToken()
33 const token = 'yes';
34 this.props.parentMethod(token);
35 }
36
37 render() {
38 return <div>This is a child.</div>;
39 }
40}
41
42export default Parent;
以下の画面キャプチャは上記のParent
を表示させたところです。
Children がマウントされたときに、親から渡された parentMethod
が実行されることによって、Parent の state が変更されて (Parentの)render が計2回呼ばれることが確認できます。
補足
上記のように初回の表示時に、2回 render() が走ってしまうことに対して、React の公式ドキュメントのcomponentDidMount()の説明に、以下のメモがあります。
You may call setState() immediately in componentDidMount(). It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won’t see the intermediate state. Use this pattern with caution because it often causes performance issues. In most cases, you should be able to assign the initial state in the constructor() instead. It can, however, be necessary for cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.
- 要約: componentDidMount()でsetState()するとrenderを2回呼ぶことになり、それはパフォーマンス上の問題になることがある。とはいえ、componentDidMount()でsetState()しなければならない場合もある。(モーダルやツールチップの表示など)
以上参考になれば幸いです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。