- 投稿日:2020-02-20T19:02:59+09:00
reactのmemoが使いこなせない
reactのmemoが使いこなせない...
【助けていただいたサイト一覧】
- 公式様
- react.memoの解説がとても分かり易かったです出発の問題
前提: react.memoの仕様の把握
react.memoを使ってパフォーマンスアップするぞーと意気込んでいました。
作業内容は、あるデータをループで回してリスト化する。あるあるです。このデータはしょっちゅう変更されますが、
// 前回データ [0:{title: 'わに'}, 1:{title: 'とり'}, 2:{title: 'いるか'} ] // 変更後データ [0:{title: 'わに'}, 1:{title: 'かば'}, 2:{title: 'やぎ'} ]であった場合、0個目のリストのpropsは変わらないので、再レンダリングするのはエコではありません。
コードで示すと以下のようになります。
parent.jsParent = () => { const [stateTest, setTest] = useState({ array: [ {title: 'わに'}, {title: 'とり'}, {title: 'いるか'} ] }) const propsChanger = () => { setTest({ array: [ {title: 'わに'}, {title: 'かば'}, {title: 'やぎ'} ] }) } let ListDom = [] stateTest.array.forEach((item) => { ListDom.push( <List objData={item} key={`list${i}`}/> ) return ( <div> {ListDom} <div onClick={propsChanger}>props更新!</div> </div> ) }List.jsexport default function List ({objData}) { console.log(`${objData.title}はレンダリング`) return( <p>{objData.title}</p> ) }再レンダリングさせない...
react.memo
の出番だ!と思ったわけです。import React, { memo } from 'react' const List = memo(({objData}) => { console.log(`${objData.title}はレンダリング`) return( <p>{objData.title}</p> ) }) export default Listメモをかませたので、shallowで比較されるはず、、!
と思って更新ボタンを押すと、わに、しっかり再レンダリングされていました...
なぜ?
オブジェクトの比較はインスタンスが違うと中身が同じでも同等と見なされないから。
memoを使いこなすのは難しそうです。解決方法!
その1 オブジェクト・配列は渡さない。
ParentstateTest.array.forEach((item, i) => { ListDom.push( <List title={item.title} key={`list${i}`}/> ) })Listconst List = memo(({title}) => { console.log(`${title}はレンダリング`) return( <p>{title}</p> ) }) export default Listpropsを文字列で渡すようにしました。これであれば わにのリストは再レンダリングされませんでした。
でも、渡す情報が多い場合は、propsをたくさん渡さなければなりません。その2 第二引数を使う
deepな比較はshallowよりコストが高いので注意です!
どうして失敗したのか
shallowでの比較の意味を取り違えていたせいです。
propsからみて一階層下の比較を行う、ということだったんですね。
渡したobject(props.object)から一回層下の比較を行う、という意味と取り違えていました。追記
https://qiita.com/takujiro_0529/items/c7eb194efefbabdb2575
こんな記事を見つけました!
まだ未検証ですが、useMemoだったら私の想定していたshallow compareになるようです!
- 投稿日:2020-02-20T17:48:22+09:00
Auth0をSPAアプリケーションでブラウザをリロードすると認証情報が消えてしまうときの対処
- 投稿日:2020-02-20T17:25:42+09:00
【React】this.setStateの即時反映
困ったこと
Formの入力欄をリアルタイムでバリデーションしたいけど,this.setStateが即時に反映されない.
.jsclass Form extends React.Component { constructor(props) { super(props); this.state = { foo: 1 }; } foo_setTwo = () => { this.state({ foo: 2 }); console.log(foo); // foo : 1 } }解決法
コールバックで呼び出すか,reactのライフサイクルでcomponentDidUpdateメソッドを使うか.
.jsfoo_setTwo = () => { this.state({ foo: 2 }, () => { console.log(foo); // foo : 2 }); } componentDidUpdate(prevProps, prevState, snapshot){ console.log(this.state.foo); // foo : 2 }