React筆記

總結

提升效能最有效的方式就是減少render()被call的次數

render後產生virtual dom若react拿virtual跟真實dom比較後有不同則更新 <-費時

會觸發rerender的情況

  1. parent change 只要parent rerender則必觸發child rerender

  2. state/context change

    props change會不會觸發rerender,props若有變是因為parent去update他,
    此時parent會rerender,所以會觸發child rerender,並不是props改變觸發rerender)

  3. hooks change (e.g. hook內state change)

    善用react-dev-tool(chrome套件)的profiler,它可以告訴你為何這個component rerender

  1. children也是prop,可以將B(component)作為prop往下傳再render它,來減少 B render的次數(因為prop改變不會觸發rerender):

    ​​​​​​​ <A><B/></A> == <A children={B}></A> 
    
  2. state往下放(減少上層Component 因state change而rerender)

  3. 笨重component跟他用到的state往下包:

    ​​​​//讓他跑到下層不要跟著上層一直rerender)    
    ​​​​<slowWrapper> 「 useState... <slowComponent /></slowWrapper> 
    
  4. useMemo讓該component只有在關注的state改變時才會rerender (value或component都可以memo) 對parent memo 無法讓child不rerender

    承上: 不要在在component裡宣告component,因為每次parant rerender都會重做一次 (解:可以用useMemo包起來

  5. memoize prop不會防止rerender 要memo整個child component

  6. useMemo + effect 組合技 減少effect觸發

  7. memo耗時的計算結果 e.g. memo一個很大的component

  8. 把context拆細一點 減少不必要context觸發一大堆component更新

    承上: memo + context 組合技 減少不必要context更新觸發rerender

  9. 使用map render list時 key作為每個item的id若key不變但內容變則react不會幫你重render

    最好用他的uniqueID當key

  10. 別用prop當state初始值

    ​​​​​​​​若props變了但該component並未重新render則state的初始不會是新的 
    ​​​​​​​​請直接用該prop或加useEffect(對應週期:componentWillReceiveProps)
    
  11. 善用PureComponent:

    PureComponent採用shallow compare
    (最多只會檢查到物件的第一層)檢查input是否相同,
    若input相同則不rerender

  12. 善用React.memo: React.memo()

    props變時A才會rerender(若該component有state改變則還是會rerender)

  13. 別在render裡宣告inline function

    因為inline function 會在檢查時({} !== {}) 失敗而觸發rerender

    不好: <A onClick={(e)=>console.log(e)}>

    好: <A onClick={print}>

  14. 更新state跟props時一律使用immutable data

    使用immutable data(創一個新的讓新的跟舊的比)可以讓compare不出錯

    ​​​​不要改舊值而是assign一個新的,像是setState
    ​​​​因為js判斷物件時採用reference而非value,
    ​​​​給他同個ref則他以為沒有變就不幫rerender了,
    
    ​​​​若該state很多層則要做immutable會很麻煩,
    ​​​​react推薦用immutable.js而不要自己deep clone
    

其他觀念:

  • data immutability 是一種 coding style:
    Whenever your object would be mutated, don’t do it. Instead, create a changed copy of it.

  • 在setState(setState是非同步的)後使用該值會是舊的

    • 所以要用useEffect(function component)或callback(class component)

其他優化

  • lazy load:
// (Component或是image)
const Home = React.lazy(() => import("./components/Home")); 
<React.Suspense fallback={<div>Loading...</div>}> <Home /> </Suspense> 
  • 使用<React.Fragment>或是<></>當wrapper避免多長html

  • 使用 react-window/react-virtualized 處理大長list

  • 分production跟development flag

參考

https://www.developerway.com/posts/react-re-renders-guide

https://blog.techbridge.cc/2018/01/05/react-render-optimization/

https://www.codementor.io/blog/react-optimization-5wiwjnf9hj