为什么你的React组件总是重复渲染?useMemo和useCallback详解

Sarah Wong | 2026-08-22T04:01:00 | JavaScript, Frontend

深入理解React性能优化,搞清楚useMemo和useCallback的正确使用场景,避免过度优化

# 为什么你的React组件总是重复渲染?useMemo和useCallback详解 ## 前言 最近Code Review的时候发现同事到处用 `useMemo` 和 `useCallback`,问他为什么,他说“性能优化啊”。但其实**乱用反而会更慢**,今天来聊聊什么时候该用,什么时候不该用。 ## 先搞清楚:React为什么会重复渲染? ```jsx // 父组件重新渲染时,子组件也会重新渲染 function Parent() { const [count, setCount] = useState(0) // 每次count变化,Child都会重新渲染 return ( setCount(count + 1)}>+1 ) } ``` ## useCallback 正确用法 ```jsx // 场景:函数作为props传给用React.memo包裹的子组件 const handleClick = useCallback(() => { console.log('点击了') }, []) // 依赖项为空,函数不会重新创建 // 子组件用React.memo包裹才有效! const Child = React.memo(({ onClick }) => { console.log('子组件渲染了') return 点击 }) ``` ## 踩坑:不该用的场景 > 我见过最离谱的用法:一个组件里每个函数都用useCallback包裹,结果React DevTools一看,渲染反而更慢了。 ```jsx // 反面教材 - 没有意义的useCallback const handleChange = useCallback((e) => { setName(e.target.value) }, []) // 这个函数又没传给子组件,包它干嘛? ``` ## useMemo 正确用法 ```jsx // 场景:计算量大的操作 const sortedList = useMemo(() => { return list.sort((a, b) => a.score - b.score) }, [list]) // 场景:引用类型作为useEffect依赖 const filters = useMemo(() => ({ status: status, type: type }), [status, type]) ``` ## 性能分析 使用React DevTools的Profiler: 1. 打开 Profiler 面板 2. 点击录制按钮 3. 操作页面 4. 查看哪些组件在不必要地重新渲染 ## 总结 - 不要无脑用 `useMemo/useCallback`,先用Profiler确认有性能问题 - `useCallback` 配合 `React.memo` 才有意义 - `useMemo` 适合计算量大的场景 - 过早优化是万恶之源

← Back to Blog