React 中hooks之 React.memo 和 useMemo用法总结
1. React.memo 基础
React.memo 是一个高阶组件(HOC),用于优化函数组件的性能,通过记忆组件渲染结果来避免不必要的重新渲染。
1.1 基本用法
const MemoizedComponent = React.memo(function MyComponent(props) {
/* 渲染逻辑 */
});
只有props发生变化才会重新渲染MemoizedComponent
1.2 带有比较函数的用法
const MemoizedComponent = React.memo(MyComponent, (prevProps, nextProps) => {
// 返回 true 表示不需要重新渲染
// 返回 false 表示需要重新渲染
return prevProps.id === nextProps.id;
});
2. React.memo 使用场景
2.1 纯展示组件
const ExpensiveComponent = React.memo(function ExpensiveComponent({ data }) {
// 复杂的渲染逻辑
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 = [/* 大量数据 */];
return (
<div>
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
<ExpensiveComponent data={data} />
</div>
);
}
2.2 列表项组件
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 来记忆回调函数
const handleItemClick = useCallback((id) => {
setSelectedId(id);
}, []);
return (
<ul>
{items.map(item => (
<ListItem
key={item.id}
item={item}
onItemClick={handleItemClick}
/>
))}
</ul>
);
}
3. useMemo 基础
useMemo 是一个 Hook,用于记忆计算结果,避免在每次渲染时重复进行昂贵的计算。
3.1 基本用法
const memoizedValue = useMemo(() => {
// 进行计算并返回结果
return computeExpensiveValue(a, b);
}, [a, b]); // 依赖项数组,空数组时只有初始化的时候执行,没有依赖参数项state每次变化都会引起重新执行,有依赖数组室,依赖数据发生变化才会触发重新执行
4. useMemo 使用场景
4.1 昂贵的计算
function DataAnalytics({ data }) {
const processedData = useMemo(() => {
// 假设这是一个复杂的数据处理函数
return data.map(item => ({
...item,
processed: expensiveOperation(item)
}));
}, [data]); // 只在 data 改变时重新计算
return (
<div>
{processedData.map(item => (
<div key={item.id}>{item.processed}</div>
))}
</div>
);
}
4.2 避免子组件不必要的重新渲染
function ParentComponent({ items }) {
// 记忆对象或数组类型的 props
const memoizedValue = useMemo(() => ({
data: items,
config: {
sortBy: 'name',
filterBy: 'active'
}
}), [items]);
return <ChildComponent options={memoizedValue} />;
}
4.3 复杂对象的派生状态
function UserDashboard({ user, transactions }) {
// 计算用户统计信息
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. 性能优化最佳实践
5.1 合理使用 React.memo
// ✅ 好的使用场景:纯组件,props 很少改变
const PureComponent = React.memo(function PureComponent({ data }) {
return <div>{/* 渲染逻辑 */}</div>;
});
// ❌ 不好的使用场景:props 经常变化
const FrequentlyChangingComponent = React.memo(function FrequentlyChangingComponent({ date }) {
return <div>{date.toLocaleTimeString()}</div>;
});
5.2 合理使用 useMemo
// ✅ 好的使用场景:计算开销大
const expensiveValue = useMemo(() => {
return someExpensiveOperation(props.data);
}, [props.data]);
// ❌ 不好的使用场景:计算开销小
const simpleValue = useMemo(() => {
return props.value + 1;
}, [props.value]); // 这种情况直接计算即可
5.3 配合 useCallback 使用
function SearchComponent({ onSearch }) {
const [query, setQuery] = useState('');
// 记忆回调函数
const handleSearch = useCallback(() => {
onSearch(query);
}, [query, onSearch]);
// 记忆计算结果
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 优化 ResultsList
const ResultsList = React.memo(function ResultsList({ results }) {
return (
<ul>
{results.map(result => (
<li key={result.id}>{result.title}</li>
))}
</ul>
);
});
6. 注意事项
-
不要过度优化
- 只在真正需要的地方使用 memo 和 useMemo
- 性能测量验证优化效果
-
依赖项的正确使用
- 确保依赖项数组包含所有需要的值
- 避免依赖项过多导致优化失效
-
避免在循环中使用 useMemo
// ❌ 错误示例 {items.map(item => { const memoizedValue = useMemo(() => compute(item), [item]); return <div>{memoizedValue}</div>; })}
-
考虑内存使用
- memo 和 useMemo 会占用额外的内存
- 在内存受限的环境中要谨慎使用
7. 性能优化决策流程
- 首先评估是否真的需要优化
- 使用 React DevTools Profiler 识别性能问题
- 选择合适的优化策略:
- 组件重新渲染优化:使用 React.memo
- 计算结果优化:使用 useMemo
- 回调函数优化:使用 useCallback
- 测试优化效果
- 持续监控性能
通过合理使用 React.memo 和 useMemo,我们可以显著提升 React 应用的性能。但记住,过度优化可能会适得其反,应该在实际需要时才进行优化。
原文地址:https://blog.csdn.net/qq_34645412/article/details/145266110
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!