在 React 中,除了 useMemo 和 useCallback,还有许多性能优化技巧可以提升应用的渲染效率和响应速度。以下是一些常用的方法:
React.memo、PureComponentReact.memo:用于包装函数组件,通过浅比较 props 来决定是否重渲染。适用于纯展示组件,且 props 变化不频繁的场景。
const MemoizedComponent = React.memo(({ name, age }) => {
// 仅当 name 或 age 浅比较变化时才重渲染
return <div>{name} - {age}</div>;
});PureComponent:类组件的优化方式,内部实现了 shouldComponentUpdate 浅比较逻辑,避免不必要的重渲染。
useSelector 按需获取状态)减少不必要的渲染。当渲染大量数据(如长列表)时,直接渲染所有元素会导致性能问题。虚拟列表只渲染可视区域内的元素,大幅减少 DOM 节点数量。
常用库:react-window、react-virtualized。
import { FixedSizeList } from 'react-window';
const LongList = ({ items }) => (
<FixedSizeList
height={500}
width="100%"
itemCount={items.length}
itemSize={50}
>
{({ index, style }) => (
<div style={style}>{items[index].name}</div>
)}
</FixedSizeList>
);通过 React.lazy 和 Suspense 实现组件的按需加载,减少初始加载的 JS 体积,提升首屏加载速度。
// 动态导入组件
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
}清理副作用:在 useEffect 中及时清理定时器、事件监听等,避免内存泄漏和无效操作。
useEffect(() => {
const timer = setInterval(() => { /* ... */ }, 1000);
return () => clearInterval(timer); // 组件卸载时清理
}, []);避免匿名函数作为 props:匿名函数每次渲染都会创建新引用,导致子组件(尤其是 React.memo 包裹的)不必要重渲染。
// 不推荐
<Child onClick={() => handleClick(id)} />
// 推荐:使用 useCallback 缓存或定义函数
const handleChildClick = useCallback(() => handleClick(id), [id]);
<Child onClick={handleChildClick} />useReducer 管理复杂状态:当状态更新逻辑复杂或多个状态相互依赖时,useReducer 可以合并更新,减少渲染次数。图片懒加载:使用 loading="lazy" 属性或第三方库(如 react-lazyload)延迟加载视口外的图片。
<img src="large-image.jpg" loading="lazy" alt="描述" />使用合适的图片格式:优先使用 WebP、AVIF 等高效格式,减少图片体积。
React.memo 自定义比较函数默认情况下,React.memo 对 props 进行浅比较。对于复杂对象(如嵌套对象、数组),可以传入自定义比较函数精确控制重渲染时机。
const MemoizedComponent = React.memo(
(props) => <div>{props.data.value}</div>,
(prevProps, nextProps) => {
// 自定义比较逻辑:仅当 data.value 变化时重渲染
return prevProps.data.value === nextProps.data.value;
}
);Context 会导致所有消费它的组件在 value 变化时重渲染,即使只使用了 value 中的一部分。可以:
将 Context 拆分为多个独立的 Context,避免无关组件被牵连。
结合 useMemo 缓存 Context 的 value,减少不必要的更新。
const Context = React.createContext();
function Provider({ children }) {
const [user, setUser] = useState({ name: 'Alice', age: 20 });
// 缓存 value,仅当 user 变化时更新
const contextValue = useMemo(() => ({ user, setUser }), [user]);
return <Context.Provider value={contextValue}>{children}</Context.Provider>;
}性能优化的核心原则是:先定位瓶颈,再针对性优化。可以通过 React DevTools 的 Profiler 工具分析渲染瓶颈,优先解决影响用户体验的关键问题(如首屏加载慢、交互卡顿)。大多数情况下,保持代码简洁清晰比过度优化更重要。