React?中hooks之?React.memo?和?useMemo用法示例總結(jié)
1. React.memo 基礎(chǔ)
React.memo 是一個(gè)高階組件(HOC),用于優(yōu)化函數(shù)組件的性能,通過(guò)記憶組件渲染結(jié)果來(lái)避免不必要的重新渲染。
1.1 基本用法
const MemoizedComponent = React.memo(function MyComponent(props) { /* 渲染邏輯 */ });
只有props發(fā)生變化才會(huì)重新渲染MemoizedComponent
1.2 帶有比較函數(shù)的用法
const MemoizedComponent = React.memo(MyComponent, (prevProps, nextProps) => { // 返回 true 表示不需要重新渲染 // 返回 false 表示需要重新渲染 return prevProps.id === nextProps.id; });
2. React.memo 使用場(chǎng)景
2.1 純展示組件
const ExpensiveComponent = React.memo(function ExpensiveComponent({ data }) { // 復(fù)雜的渲染邏輯 return ( <div> {data.map(item => ( <div key={item.id}> <h3>{item.title}</h3> <p>{item.description}</p> </div> ))} </div> ); }); // 父組件 function ParentComponent() { const [count, setCount] = useState(0); const data = [/* 大量數(shù)據(jù) */]; return ( <div> <button onClick={() => setCount(c => c + 1)}> Count: {count} </button> <ExpensiveComponent data={data} /> </div> ); }
2.2 列表項(xiàng)組件
const ListItem = React.memo(function ListItem({ item, onItemClick }) { console.log(`Rendering item ${item.id}`); return ( <li onClick={() => onItemClick(item.id)}> {item.name} </li> ); }); function List({ items }) { const [selectedId, setSelectedId] = useState(null); // 使用 useCallback 來(lái)記憶回調(diào)函數(shù) const handleItemClick = useCallback((id) => { setSelectedId(id); }, []); return ( <ul> {items.map(item => ( <ListItem key={item.id} item={item} onItemClick={handleItemClick} /> ))} </ul> ); }
3. useMemo 基礎(chǔ)
useMemo 是一個(gè) Hook,用于記憶計(jì)算結(jié)果,避免在每次渲染時(shí)重復(fù)進(jìn)行昂貴的計(jì)算。
3.1 基本用法
const memoizedValue = useMemo(() => { // 進(jìn)行計(jì)算并返回結(jié)果 return computeExpensiveValue(a, b); }, [a, b]); // 依賴(lài)項(xiàng)數(shù)組,空數(shù)組時(shí)只有初始化的時(shí)候執(zhí)行,沒(méi)有依賴(lài)參數(shù)項(xiàng)state每次變化都會(huì)引起重新執(zhí)行,有依賴(lài)數(shù)組室,依賴(lài)數(shù)據(jù)發(fā)生變化才會(huì)觸發(fā)重新執(zhí)行
4. useMemo 使用場(chǎng)景
4.1 昂貴的計(jì)算
function DataAnalytics({ data }) { const processedData = useMemo(() => { // 假設(shè)這是一個(gè)復(fù)雜的數(shù)據(jù)處理函數(shù) return data.map(item => ({ ...item, processed: expensiveOperation(item) })); }, [data]); // 只在 data 改變時(shí)重新計(jì)算 return ( <div> {processedData.map(item => ( <div key={item.id}>{item.processed}</div> ))} </div> ); }
4.2 避免子組件不必要的重新渲染
function ParentComponent({ items }) { // 記憶對(duì)象或數(shù)組類(lèi)型的 props const memoizedValue = useMemo(() => ({ data: items, config: { sortBy: 'name', filterBy: 'active' } }), [items]); return <ChildComponent options={memoizedValue} />; }
4.3 復(fù)雜對(duì)象的派生狀態(tài)
function UserDashboard({ user, transactions }) { // 計(jì)算用戶(hù)統(tǒng)計(jì)信息 const userStats = useMemo(() => { return { totalSpent: transactions.reduce((sum, t) => sum + t.amount, 0), averageSpent: transactions.length ? transactions.reduce((sum, t) => sum + t.amount, 0) / transactions.length : 0, mostFrequentCategory: calculateMostFrequentCategory(transactions) }; }, [transactions]); return ( <div> <UserInfo user={user} /> <UserStatistics stats={userStats} /> </div> ); }
5. 性能優(yōu)化最佳實(shí)踐
5.1 合理使用 React.memo
// ? 好的使用場(chǎng)景:純組件,props 很少改變 const PureComponent = React.memo(function PureComponent({ data }) { return <div>{/* 渲染邏輯 */}</div>; }); // ? 不好的使用場(chǎng)景:props 經(jīng)常變化 const FrequentlyChangingComponent = React.memo(function FrequentlyChangingComponent({ date }) { return <div>{date.toLocaleTimeString()}</div>; });
5.2 合理使用 useMemo
// ? 好的使用場(chǎng)景:計(jì)算開(kāi)銷(xiāo)大 const expensiveValue = useMemo(() => { return someExpensiveOperation(props.data); }, [props.data]); // ? 不好的使用場(chǎng)景:計(jì)算開(kāi)銷(xiāo)小 const simpleValue = useMemo(() => { return props.value + 1; }, [props.value]); // 這種情況直接計(jì)算即可
5.3 配合 useCallback 使用
function SearchComponent({ onSearch }) { const [query, setQuery] = useState(''); // 記憶回調(diào)函數(shù) const handleSearch = useCallback(() => { onSearch(query); }, [query, onSearch]); // 記憶計(jì)算結(jié)果 const searchResults = useMemo(() => { return performExpensiveSearch(query); }, [query]); return ( <div> <input value={query} onChange={e => setQuery(e.target.value)} /> <button onClick={handleSearch}>搜索</button> <ResultsList results={searchResults} /> </div> ); } // 使用 React.memo 優(yōu)化 ResultsList const ResultsList = React.memo(function ResultsList({ results }) { return ( <ul> {results.map(result => ( <li key={result.id}>{result.title}</li> ))} </ul> ); });
6. 注意事項(xiàng)
不要過(guò)度優(yōu)化
- 只在真正需要的地方使用 memo 和 useMemo
- 性能測(cè)量驗(yàn)證優(yōu)化效果
依賴(lài)項(xiàng)的正確使用
- 確保依賴(lài)項(xiàng)數(shù)組包含所有需要的值
- 避免依賴(lài)項(xiàng)過(guò)多導(dǎo)致優(yōu)化失效
避免在循環(huán)中使用 useMemo
// ? 錯(cuò)誤示例 {items.map(item => { const memoizedValue = useMemo(() => compute(item), [item]); return <div>{memoizedValue}</div>; })}
考慮內(nèi)存使用
- memo 和 useMemo 會(huì)占用額外的內(nèi)存
- 在內(nèi)存受限的環(huán)境中要謹(jǐn)慎使用
7. 性能優(yōu)化決策流程
- 首先評(píng)估是否真的需要優(yōu)化
- 使用 React DevTools Profiler 識(shí)別性能問(wèn)題
- 選擇合適的優(yōu)化策略:
- 組件重新渲染優(yōu)化:使用 React.memo
- 計(jì)算結(jié)果優(yōu)化:使用 useMemo
- 回調(diào)函數(shù)優(yōu)化:使用 useCallback
- 測(cè)試優(yōu)化效果
- 持續(xù)監(jiān)控性能
通過(guò)合理使用 React.memo 和 useMemo,我們可以顯著提升 React 應(yīng)用的性能。但記住,過(guò)度優(yōu)化可能會(huì)適得其反,應(yīng)該在實(shí)際需要時(shí)才進(jìn)行優(yōu)化。
到此這篇關(guān)于React 中hooks之 React.memo 和 useMemo用法總結(jié)的文章就介紹到這了,更多相關(guān)React React.memo 和 useMemo內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react-redux中connect的裝飾器用法@connect詳解
這篇文章主要介紹了react-redux中connect的裝飾器用法@connect詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01React-Native做一個(gè)文本輸入框組件的實(shí)現(xiàn)代碼
這篇文章主要介紹了React-Native做一個(gè)文本輸入框組件的實(shí)現(xiàn)代碼,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-08-08React工作流程及Error Boundaries實(shí)現(xiàn)過(guò)程講解
這篇文章主要介紹了React工作流程及Error Boundaries實(shí)現(xiàn)過(guò)程講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-02-02React+Typescript創(chuàng)建項(xiàng)目的實(shí)現(xiàn)步驟
通過(guò)React組件庫(kù)和TypeScript的強(qiáng)類(lèi)型特性,開(kāi)發(fā)者可以創(chuàng)建出具有優(yōu)秀用戶(hù)體驗(yàn)和穩(wěn)定性的Web應(yīng)用程序,本文主要介紹了React+Typescript創(chuàng)建項(xiàng)目的實(shí)現(xiàn)步驟,感興趣的可以了解一下2023-08-08React?Hooks--useEffect代替常用生命周期函數(shù)方式
這篇文章主要介紹了React?Hooks--useEffect代替常用生命周期函數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09React Ant Design樹(shù)形表格的復(fù)雜增刪改操作
這篇文章主要介紹了React Ant Design樹(shù)形表格的復(fù)雜增刪改操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11