React.memo
React.memo 是一个高阶组件(HOC),用于
优化函数组件的渲染性能
。它通过浅比较组件的 props 变化来决定是否重新渲染组件。如果 props 未变化,则复用上一次的渲染结果。
基本用法
将函数组件包裹在 React.memo
中即可:
ts
const MyComponent = React.memo(function MyComponent(props) {
// 组件逻辑
});
或使用箭头函数:
ts
const MyComponent = React.memo((props) => {
// 组件逻辑
});
自定义比较函数
默认情况下,React.memo
会对 props 进行浅比较。如果需要自定义比较逻辑,可以传入第二个参数:
ts
const areEqual = (prevProps, nextProps) => {
// 返回 true 表示跳过渲染,false 表示重新渲染
return prevProps.value === nextProps.value;
};
const MyComponent = React.memo((props) => {
// 组件逻辑
}, areEqual);
适用场景
- 组件渲染开销较大(如复杂计算或频繁渲染)。
- 父组件频繁更新,但
子组件
的 props 未变化。 - 纯展示型组件(无内部状态或副作用)。
注意事项
- 仅对 props 进行比较,不影响组件内部状态(state)或上下文(context)的变化。
- 浅比较可能无法检测对象或数组内部的变化,需确保 props 是稳定引用。
- 过度使用可能导致性能反而下降(比较逻辑本身消耗资源)。
与类组件的区别
类组件类似的功能可通过 React.PureComponent
或手动实现 shouldComponentUpdate
实现。React.memo
是函数组件的等效优化手段。
小栗子
ts
import React, {useState} from 'react';
import './index.css';
interface userCard {
name: string;
age: number;
phone: string;
}
// 未使用memo
// const Child = (props: {userData:userCard}) => {
// 使用memo
const Child = React.memo((props: {userData:userCard}) => {
// 将userData解构出来
const {userData} = props;
console.log('子组件渲染了');
return (
<div className='userCard'>
<p>{userData.name}</p>
<p>{userData.age} 岁</p>
<p>{userData.phone}</p>
</div>
)
})
export const App = () => {
const [input, setInput] = useState('')
const [user, setUser] = useState({
name: '张三',
age: 18,
phone: '12345678901'
})
const handleBtnClick = () => {
setUser({
name: input,
age: 18,
phone: '12345678901'
})
}
return (
<div>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
style={{
padding: '8px 12px',
border: '1px solid #000',
borderRadius: '4px',
fontSize: '14px',
marginRight: '8px'
}}
/>
<button
onClick={handleBtnClick}
style={{
padding: '8px 16px',
backgroundColor: '#fff',
color: '#000',
border: '1px solid #000',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '14px'
}}
>
更改数据
</button>
<Child userData={user} />
</div>
)
}
export default App
结果如下:
在未使用memo时,只要state的值发生变化都会导致组件重新渲染,这样就很大程度上造成了资源的浪费。
使用memo之后,只有当子组件依赖的内容发生变化时才会重新去渲染。
useMemo
useMemo
是 React 中的一个 Hook,用于优化性能,通过缓存计算结果避免不必要的重复计算。它接受一个函数和依赖项数组,仅在依赖项发生变化时重新计算值。
useMemo 的语法
javascript
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
- 第一个参数:计算函数,返回需要缓存的值。
- 第二个参数:依赖项数组,数组中的值变化时才会重新计算(类似于useEffect)。
useMemo 的适用场景
优化计算密集型操作
当组件中有高开销的计算(如复杂数学运算、大数据处理)时,useMemo
可以避免每次渲染都重新计算。
避免不必要的子组件渲染
结合 React.memo
使用,可以防止子组件因父组件无关状态更新而重复渲染。
缓存引用类型数据
对于对象或数组等引用类型,useMemo
可以避免每次渲染生成新引用,减少子组件的不必要更新。
useMemo 的注意事项
避免过度使用
useMemo
本身有性能开销,仅在高开销计算或引用稳定性关键时使用。简单计算可能得不偿失。
依赖项需明确
遗漏依赖项可能导致缓存值不更新,错误地使用旧值。确保依赖项完整且准确。
不用于副作用
useMemo
应用于纯计算逻辑,副作用(如数据请求、DOM 操作)应使用 useEffect
。
useMemo 与 useCallback 的区别
useMemo
缓存计算结果(如数值、对象)。useCallback
缓存函数本身,避免函数引用变化。
代码示例
javascript
import React, { useMemo, useState } from 'react';
function Sum({ n }) {
// 使用useMemo(数据处理的方法, [依赖项]),只有当依赖项发生改变时才会重新执行数据处理方法 返回值:useMemo返回的时普通值
const total = useMemo(() => {
console.log('重新计算和');
return (n * (n + 1)) / 2;
}, [n]);
return <h1>1+2+...+{n} = {total}</h1>;
}
export default function App() {
const [n, setN] = useState(5);
const [v, setV] = useState(0); // 与计算无关的状态
return (
<>
<Sum n={n} />
<button onClick={() => setN(n + 1)}>n+1</button>
<button onClick={() => setV(v + 1)}>无关渲染 {v}</button>
</>
);
}
通过合理使用 useMemo
,可以显著提升 React 组件的性能表现。