作用:
useMemo主要用來解決使用React hooks產生的無用渲染的性能問題。
緣由:
使用function的形式來聲明組件,失去了shouldCompnentUpdate(在組件更新之前)這個生命周期,主要進行狀態對比,如果需要則進行改變。
也就是說使用Hooks的useEffect(替代生命周期)后我們沒有辦法通過組件更新前條件來決定組件是否更新。
而且在函數組件中,也不再區分mount和update兩個狀態,這意味着函數組件的每一次調用都會執行內部的所有邏輯,就帶來了非常大的性能損耗,例如子組件里有異步請求,那每次執行都會
請求一次。
方案:
useMemo和useCallback都是解決上述性能問題的,本節先介紹useMemo.
主體:
下面我們通過一個實例,來理解下 useMemo的用法。
- 父組件
function App() { const [name, setName] = useState('名稱') const [content,setContent] = useState('內容') return ( <> <button onClick={() => setName(new Date().getTime())}>name</button> <button onClick={() => setContent(new Date().getTime())}>content</button> <Button name={name}>{content}</Button> </> ) }
- 子組件
function Button({ name, children }) { function changeName(name) { console.log('11') return name + '改變name的方法' } const otherName = changeName(name) return ( <> <div>{otherName}</div> <div>{children}</div> </> ) }
熟悉react的同學可以很顯然的看出,當我們點擊父組件的按鈕的時候,子組件的name和children都會發生變化。
注意我們打印console.log的方法。
不管我們是改變name或者content的值,我們發現 changeName的方法都會被調用。 是不是意味着 我們本來只想修改content的值,但是由於name並沒有發生變化,所以無需執行對應的changeName方法。但是發現他卻執行了。 這是不是就意味着性能的損耗,做了無用功。
下面我們使用useMemo進行優化
- 優化之后的子組件
function Button({ name, children }) { function changeName(name) { console.log('11') return name + '改變name的方法' } const otherName = useMemo(()=>changeName(name),[name]) return ( <> <div>{otherName}</div> <div>{children}</div> </> ) } export default Button
這個時候我們點擊 改變content值的按鈕,發現changeName 並沒有被調用。 但是點擊改變name值按鈕的時候,changeName被調用了。
結語
所以我們可以使用useMemo方法,避免無用方法的調用,當然一般我們changName里面可能會使用useState來改變state的值,那是不是就避免了組件的二次渲染,達到了優化性能的目的。
.