一、useMemo
基本用法:useMemo
是 React 提供的一个 Hook,用于性能优化,它通过"记忆"(memoization)计算结果来避免在每次渲染时进行不必要的复杂计算。
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useMemo
会检查依赖项数组中的值是否发生变化,只有当依赖项变化时,才会重新执行计算函数,否则直接返回之前缓存的值useMemo
可以显著提高性能,避免在每次渲染时都执行昂贵的计算useMemo
可以保持引用不变(除非依赖项变化),这对于传递给子组件的 props 特别有用,可以避免不必要的子组件重新渲染function ExpensiveComponent({ a, b }) {
const result = useMemo(() => {
// 复杂的计算过程
return a * b + Math.pow(a, b) - a / b;
}, [a, b]); // 只有当a或b变化时才重新计算
return {result};
}
function ParentComponent({ items }) {
const processedItems = useMemo(() => {
return items.map(item => ({
...item,
fullName: `${item.firstName} ${item.lastName}`
}));
}, [items]); // 只有当items变化时才重新处理
return ;
}
function FormComponent({ onSubmit }) {
const formConfig = useMemo(() => ({
initialValues: { username: '', password: '' },
validate: values => {
const errors = {};
if (!values.username) errors.username = 'Required';
return errors;
}
}), []); // 空依赖数组表示只创建一次
return ;
}
useMemo
本身也有性能开销,只对真正昂贵的计算或需要稳定引用的值使用useMemo
来实现业务逻辑的正确性React.memo
的区别:useMemo
记忆的是值,React.memo
记忆的是组件useCallback
基本用法:useCallback
是 React 提供的用于性能优化的 Hook,它的主要作用是缓存函数引用,避免不必要的函数重新创建。
// 不使用 useCallback - 每次渲染都会创建新函数,导致 useEffect 重复执行
const fetchData = () => { /*...*/ };
useEffect(() => {
fetchData();
}, [fetchData]); // 依赖项每次都会变化
// 使用 useCallback - 只有依赖变化时才创建新函数
const fetchData = useCallback(() => {
/*...*/
}, [dependency]); // 只有当 dependency 变化时才重新创建函数
// 子组件用 React.memo 优化过
const Child = React.memo(({ onClick }) => {
/*...*/
});
function Parent() {
// 不使用 useCallback - 每次渲染都会导致 Child 重新渲染
const handleClick = () => { /*...*/ };
// 使用 useCallback - 避免 Child 不必要的重新渲染
const handleClick = useCallback(() => {
/*...*/
}, []); // 空依赖表示函数永不变化
return ;
}
function useCounter() {
const [count, setCount] = useState(0);
// 返回稳定的函数引用
const increment = useCallback(() => setCount(c => c + 1), []);
const decrement = useCallback(() => setCount(c => c - 1), []);
return { count, increment, decrement };
}
函数被包含在依赖数组(如 useEffect
、useMemo
、useCallback
的依赖数组)中时
函数作为 prop 传递给用 React.memo
优化的子组件时
函数被用作上下文值且会被多个组件使用时
函数被多次创建且创建成本较高时(虽然这种情况较少见)
useCallback
的情况useCallback
的关系: useCallback(fn, deps)
相当于 useMemo(() => fn, deps)
,两者都用于性能优化,但:
useMemo
用于记忆计算结果useCallback
专门用于记忆函数// 这两个是等价的
const memoizedCallback = useCallback(() => doSomething(a, b), [a, b]);
const memoizedCallback = useMemo(() => () => doSomething(a, b), [a, b]);