ReactNativeで renderメソッドにonpress={this.setState{…}}は何でダメなのか?
質問サイトで、こんな質問がありました。
「ReactNativeで renderメソッドにonpress={this.setState{…}}になっている場合、
画面が真っ白になり、componentが表示されない。
onPress={this.setState({isModalVisible: true})}
このような記述になっていると、setStateがひたすら呼ばれています、consoleを確認したところ、それと同時にrenderメソッドが呼ばれていた模様。そもそも何でひたすらsetStateが呼び出されるのか。」
私が、その質問サイトに答えを書きましたが、実はここが重要な基礎にも関わらず、しっかり理解していない方も多いようです。
私自身も同じことをした経験もありますし、タイムチケットで、このような質問もありました。
やはり、みんな共通して認識の曖昧なところかもしれませんので
ここで記事にまとめてみました。
回答
①
renderメソッドはReact Nativeの管理下に置かれています。
我々何もしなくても、ReactNativeが勝手に必要なとき、renderメソッドを呼び出します。
何らかの変化があったら、renderメソッドは呼び出されます。
②
Buttonとかのコンポーネントの仕様書を見る限り
onPress=の後ろはFunctionが来ることになっています。
つまり
onPress={() => {this.setState({isModalVisible: true})}}
が正しいです。
こうすることによって、Buttonが押された時に実行されるべきFunctionをReactNativeに教えます。ReactNativeは約束通りにやることをやります。
() => {this.setState({isModalVisible: true})}
イコール
function myFunc(){ this.setState({isModalVisible: true}) }
ここで、ボタンを押したら実行する関数なので名前がなくてもいいので、()=>{}という形になっています。
では、なぜ
onPress={this.setState({isModalVisible: true})}
がダメなのかと言いますと(私の理解で言語化してみますが)
ここは関数ではなく、評価式です。
{}の中の部分は普通にプログラムの一部として、ReactNativeがrenderメソッドの中に遭遇したら、即実行します。
例えば、<View style={styles.container}>のように
{}の部分は、実際に「プログラム」として実行され、実行の結果として具体的なstyleを取って来ることになります。
onPress={this.setState({isModalVisible: true})}
ですと、「押されたら、これを実行してね」になっていないからです。
①で説明したように、上は「評価式で、ただのプログラム」ですから、renderメソッドに入っていて、一回実行されると、何か変化したこと(setStateしたから)になって、またrenderメソッドが実行され、その次も、その次もと無限ループになります。
まとめ
いかがでしょうか?
実は、ここがうっかりミスした場合が結構多くて
これからは、onPressのところではしっかり関数を設定してあげるようにしましょう。
あと、補足ですが、render()メソッドには、onPressのところだけではなく、this.setState()は避けたほうがいいですね。this.setStateを使うと、上記のように無限ループになります。
ではまた!
[amazonjs asin=”B078KDYXSG” locale=”JP” title=”React Nativeで初めるiOS・Androidクロスプラットフォームアプリ開発入門 – その1”]