Why
除了React本身的渲染機制外,畫面被渲染出來前,也會執行一連串符合需求、我們自定義的運算,當元件重新渲染時,我們不希望某些數據被重算,這時我們希望這個數據可以被記憶起來。
比如說 Hello world 常見的印星星 ******
我們根據某個變數 count 來決定要印幾顆星星,那今天這個 count 不變
假如這是一個很貴的運算,我們不希望他被重新運算,所以就會想把這個結果記憶起來
於是乎,我們就可以派出 useMemo 了。
// 印星星
let stars = "";
for (let i = 1; i <= count; i += 1) {
stars += "*";
}
how
使用 React 強大的API,useMemo
Demo codesanbox Link
show me the code
const result = useMemo(() => {
let stars = "";
for (let i = 1; i <= count; i += 1) {
stars += "*";
}
return stars;
}, [count]); //dep array 中的count,假設是元件內某個state 或props
return (
<div>
<h1>{result}</h1>
</div>
)
今天的範例當中,一時間想不到什麼太複雜、昂貴的運算,就決定使用 Math.random() 來當例子啦!
我們的元件中,有兩個state,其中有個state 跟亂數有關,另一個沒有。
我希望只有這個跟亂數有關的state 改變,畫面才會產生新的亂數。另一個狀態改變時,這個亂數在畫面上維持不變 (不會被重新渲染)。
const [radomDepState, setRadomDepState] = useState(1);
const [count, setCount] = useState(1);
const random = ???????
// ------------------------------------------------
<h1>{random}</h1>
現在我們有兩個state,一個跟radom有關,另一個沒有,畫面上也有個random,這個random會長這樣:
function createRandomNumber() {
return parseInt(1000 * Math.random());
}
const random = createRandomNumber()
接著我們希望有些機制,可以改變 radomDepState / count 這兩個狀態
因此我們加入了兩個button,並且在畫面上顯示這兩個state。
{count}
<button onClick={() => setCount(count + 1)}>
不相關的state
</button>
{radomDepState}
<button onClick={() => setRadomDepState(radomDepState + 1)}>
useMemo依賴的radomDepState
</button>
此時,我們點任何一個按鈕,畫面上的亂數都會跳來跳去、不停地改變
接著來調整一下原本的random,思考一下useMemo 會被如何使用呢?
const random = useMemo(doing something here);
9/19修正描述, 官網說 useMemo 吃兩個參數 useMemo( fn , dependencies ) 【React】官網是說:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
想當然爾,第一個fn computeExpensiveValue
當然就是我們昂貴計算的本人啦!本範例就是那個createRandomNumber了啊。 因為我們不希望亂數一直被改變。
而官網又說第二個參數是個Array,我們不管,就先帶入一個空陣列 [] 進去看看。
const random = useMemo(() => createRandomNumber(), []);
此時我們發現,各自點擊按鈕時,畫面上的 count / radomDepState 都會跟著改變!
但唯獨~~~~~!!!!!!!! 我們的 random 自此致終不再改變過QwQ
這跟我們想要的情境不一樣啊~~~~
我希望是點影響radomDepState的那顆按鈕,我們就要產生新的亂數
9/19修正描述, useMemo( fn , dependencies ) 【React】官網是說:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
此時回頭看看,第二個dependencies,英文單字說文解字 依存關係 / 依屬 WTF~~
原來這就是那個,當有什麼東西發生改變時,我們要重新進行這個昂貴運算的依賴。
那些 state / props 也就是 我們所謂的依賴。
既然用了「那些」,代表這可以是一個複數群,因此我們的dependencies是用array儲存起來。
// const random = useMemo(() => createRandomNumber(), [radomDepState]);
// 我們直接來個簡寫好了
const random = useMemo(() => {
return parseInt(1000 * Math.random());
}, [radomDepState]);
此時,我們可以看到,當count改變時,我們的random不會變成其他隨機數字。但radomDepState改變時,我們就會產新的亂數!
如果你在 render 當中執行了昂貴的計算,你可以使用 useMemo 來最佳化。React 官網
你可以把 useMemo 作為效能最佳化的手段,但請不要把它當作成語意上的保證。 React 官網
意思是說,不是什麼東西丟到useMemo 就是效能優化,提醒我們不要無限上綱的亂用XD!
這邊也要注意到,useMemo 在 React 當中,被執行的時機是在render當中,而不是render結束時。(不像是useEffect,是在畫面渲染完後執行)
所以我們要避免一些會阻礙畫面渲染的事情,比如說call API 之類的side Effect。
要謹記傳到 useMemo 的 function 會在 render 期間執行。不要做一些通常不會在 render 期間做的事情。例如,處理 side effect 屬於 useEffect,而不是 useMemo
React 官網
React 性能優化那件大事,使用 memo、useCallback、useMemo
(https://medium.com/%E6%89%8B%E5%AF%AB%E7%AD%86%E8%A8%98/react-optimize-performance-using-memo-usecallback-usememo-a76b6b272df3)
Ya~~~~ 完成任務啦! 我指第三天的....
明天繼續努力