1. 理解重新渲染
定义:
当组件的状态(state)或属性(props)变更时,会触发重新渲染。默认情况下,当一个组件重新渲染时, React 将递归渲染它的所有子组件。
✅ 核心要点
- React 对比新旧虚拟 DOM,执行协调过程。
- 即使输出结果相同,协调过程仍会发生。
- React 仅在渲染之间存在差异时才会更改 DOM 节点。
⚠️ 注意事项
- 传递新的对象/数组会触发子组件的重新渲染:
<MyComp data={{x:1}} /> // 每次渲染生成新对象
- Context 更新会重新渲染所有消费者(consumers)。
- React.memo 仅在属性浅层比较相等时阻止重新渲染。
🎯 面试一句话总结
重新渲染由状态/属性变更或父组件更新触发。传递新对象引用或 Context 变更往往是性能瓶颈的根源。
2. React.memo, useMemo, useCallback
✅ React.memo
- 包裹组件,对属性进行浅层比较。
- 避免不必要的重新渲染。
✅ useMemo
- 在渲染间缓存值。
- 用于昂贵计算或派生值。
✅ useCallback
- 缓存函数,避免创建新函数引用。
- 适用于向已记忆化的子组件传递回调。
⚠️ 注意事项
- useMemo/useCallback 本身有成本,仅在必要时使用。
- 浅层比较无法检测嵌套对象变更。
- 过度使用可能反而降低性能。
🎯 面试一句话总结
React.memo 通过属性浅比较避免重渲染。useMemo 缓存值,useCallback 缓存函数,滥用可能适得其反。
3. 批量更新(Batching Updates)
定义:
React 将多次状态更新合并为单次渲染。
✅ React 18 之前
- 批量更新仅发生在事件处理函数内。
✅ React 18+
- 批量更新扩展至所有上下文(定时器、异步回调、Promise)。
示例:
setCount(c => c+1);
setValue(v => v+1);
// React 18 → 触发一次渲染
🎯 面试一句话总结
React 18 实现全场景自动批量更新,减少渲染次数。此前仅限事件处理函数内。
4. 并发渲染(Concurrent Rendering)
定义:
React 18 的并发模式(默认启用)允许根据优先级中断、暂停或重启渲染。
✅ 核心要点
- 支持时间切片(time slicing)— 渲染期间保持 UI 响应。
- 新增 API:useTransition, useDeferredValue。
- 不改变最终 UI,仅优化 React 调度策略。
⚠️ 注意事项
- 提交前可能经历多次渲染过程。
- 副作用需放入提交阶段(用 useEffect,而非渲染函数)。
🎯 面试一句话总结
并发渲染使 React 可按优先级暂停/恢复工作。它不改变 UI 结果,仅优化调度逻辑。
5. useTransition & useDeferredValue
✅ useTransition
- 拆分更新为紧急与非紧急。
- 确保重型渲染期间 UI 响应性:
const [isPending, startTransition] = useTransition();
startTransition(() => setSearchResults(expensiveCompute(query)));
✅ useDeferredValue
- 延迟更新值直至空闲时段:
const deferredQuery = useDeferredValue(query);
🎯 面试一句话总结
useTransition 标记非紧急更新以保持响应;useDeferredValue 推迟高成本渲染至空闲时段。
6. 虚拟化(大型列表)
定义:
仅渲染列表中可见项,而非一次性处理全部。
✅ 推荐库
react-window, react-virtualized。
✅ 优势
- 大幅提升万级列表性能。
- 显著减少 DOM 节点数量。
⚠️ 注意事项
- 需精确计算高度(行高/列宽)。
- 隐藏元素影响可访问性与 SEO。
🎯 面试一句话总结
虚拟列表仅渲染可见列表项,对海量数据渲染优化至关重要,但需妥善处理高度计算与可访问性。
7. Suspense 数据获取
定义:
Suspense 允许组件在渲染后备方案前“等待”异步数据。
✅ 核心要点
- Suspense 边界避免瀑布流请求。
- 需配合 React 数据框架(如 Next.js, Relay)使用。
- 支持流式服务端渲染(SSR)。
⚠️ 注意事项
- 仅处理 Promise 而非任意异步操作。
- 错误处理需依赖错误边界。
🎯 面试一句话总结
Suspense 使 React 能通过后备方案等待异步数据,简化异步逻辑,但需用错误边界捕获异常。
8. 避免高成本渲染
✅ 优化技术
- 虚拟化(Virtualization)长列表。
- 防抖/节流(Debouncing/Throttling)用户输入。
- 懒加载组件(React.lazy)。
- 精细化 Context(拆分 Provider)。
- 选择器钩子(Selector hooks)订阅状态切片。
🎯 面试一句话总结
通过记忆化、列表虚拟、输入防抖、代码懒加载及状态上下文拆分优化渲染性能。
9. 性能调试 (Debugging Performance)
✅ 工具 (Tools)
- React DevTools 性能分析器(渲染火焰图)
- why-did-you-render 库(检测非必要渲染)
- 浏览器性能标签页
✅ 常见问题
- 渲染风暴(Re-render storms):短时间内密集触发多次渲染
- 输入延迟(Input lag):用户交互响应卡顿
- UI 闪烁(Flickering UI):界面元素异常抖动或重绘
🎯 面试一句话总结
通过 React DevTools 和 why-did-you-render 定位渲染风暴;输入延迟或 UI 闪烁通常由无效渲染引起。