概要
reactでsetStateしてもrenderメソッドが動かなくて困った。
先に結論
親のコンポーネントからmap関数でこのコンポーネントをループ処理で作成しているが、key属性を指定してあげると再描画された。
やってみたこと
なんでかなー、と思ってshouldComponentUpdate
の中でログを出してみた。
shouldComponentUpdate (nextProps, nextState){
console.log("stateって変わったの?");
const propsDiff = _.isEqual(nextProps, this.props);
const stateDiff = _.isEqual(nextState, this.state);
return !(propsDiff && stateDiff);
}
これをやってみると、一応ログは出せるのでstateの変更は起きている。
再描画されないけどshouldComponentUpdate
まで来ているということは…。
nextState
とthis.state
の値が同じ!?、でもそんなことないか、
と思いながらログを出してみると、
shouldComponentUpdate (nextProps, nextState){
console.log("stateって変わったの?");
const propsDiff = _.isEqual(nextProps, this.props);
const stateDiff = _.isEqual(nextState, this.state);
console.log(nextState);
console.log(this.state);
return !(propsDiff && stateDiff);
}
まさかの同じだった。
this.state
は変更前のstateの値が入るはずなのに変更後の値が入って来ていた。
いろいろと調べ物をしている時に、Reactはコンポーネントごとに独自のidみたいなのを割り当て、stateの変更があったら、コンポーネント独自のidと差分のデータをもとに画面を更新する、みたいなことを読んだ。
そういやいままで、map関数を使ってコンポーネントを複製している部分で
bundle.js:4233 Warning: Each child in an array or iterator should have a unique "key" prop.
というエラーが出ていたが、ちゃんとコンポーネントが複製されているし、いっか〜、みたいなノリでこのエラーを無視していた。
しかし、key属性をつけることで、このコンポーネントに独自のidが割り当てられるようになり、stateの変更があった際も、このidのコンポーネントのstateの値が変わった、ということを検知してくれて再描画されるのでは、という仮説を立ててkey属性をつけてみたら、再描画された!shouldComponentUpdate
のthis.state
の値も変更前の値になっていたし解決!!
ただ、残る疑問は、なぜ、key属性をつけない場合のshouldComponentUpdate
のthis.state
の値が、なぜ変更後の値になっているかということは解決されていないが…。
ここに関してわかる方、教えていただきたいです。