🦔
Reactの再描画について調べた
reactの再描画はどのタイミングで行われるのか気になったので調査しました。
間違えてる点があれば光の速さで直すので指摘してください。
再描画されるタイミング
基本的に以下が呼ばれた後にpropsが比較され、必要があれば再描画されます。
- class component
- this.setState()
- this.forceUpdate()
- Function component
- useState
- useRender
親componentが再描画されれば基本的に子componentはすべて再描画されます。(propsが変わっていようがいまいがかかわらず)
比較方法
shallow compare が使われます。
const object = { a: 1, b: 2 };
object === object // true
object === { a: 1, b: 2 } // false
object === { ...object } // false
中身まで確認しないので比較コストが低いです。
再描画を防ぐためには
再描画されるタイミングで関数や値は別の参照のインスタンスが作られてしまうために再描画されていました。
関数や値は同じ参照のインスタンスが渡されるようにし、子componentがprops比較してから再描画されるようにす必要があります。
useCallback
, useMemo
, React.memo
を使って最適化することができます。
再描画される例
以下の例だと親が再描画されると新しい参照が渡されてしまうので子componentは再描画されてしまいます。
const MemolizedChildComponent = React.memo(props => <ChildComponent { ...props } />);
const ParentComponent = () => {
const func = () => {
console.log(1)
}
const obj = { hoge: "a" };
return <MemolizedChildComponent obj={obj} func={func} />
}
再描画されない例
以下の例だと、親が再描画されても同じ参照を返すので子componentは再描画されません。
const MemolizedChildComponent = React.memo(props => <ChildComponent { ...props } />);
const ParentComponent = () => {
const func = useCallback(() => {
console.log(1)
}, [])
const obj = useMemo(() => ({ hoge: "a" }), []) ;
return <MemolizedChildComponent obj={obj} func={func} />
}
もちろんメモ化するということはコストがかかってしまうのですべてに使ってしまえばいいわけではありません。
いつuseCallback
useMemo
を使うか迷ったときは
- 同じ参照のインスタンスを渡したいのか
- コストの高い計算があるか
このことを意識するのが大切です。
Discussion
const value = useMemo(() =>1, []) ;
これはプリミティブな数値だからconst value = 1;
のままで大丈夫かと思います!(試していませんが、多分…!)その通りです!光の速さで修正します。ありがとうございます!!