4.1 KiB
id, title, type, domain, stack, tags, level, related, week
| id | title | type | domain | stack | tags | level | related | week | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| frontend.react.interview | React 面试题 | interview | frontend |
|
|
intermediate |
|
|
React 面试题
基础
【基础】React 组件什么时候会重新渲染?
参考答案:自身 state 变化、父组件渲染(即使 props 没变)、使用的 Context 值变化。渲染不等于 DOM 更新,React 会比较后只提交变化的部分。
追问:怎么避免子组件不必要的渲染?→ memo 包裹子组件并保证 props 引用稳定(useMemo / useCallback),或者把状态下移、把变化的部分拆成独立组件;React Compiler 可以自动处理部分记忆化。
【基础】为什么 Hooks 不能写在条件语句中?
参考答案:React 用 Hook 的调用顺序来对应每个 Hook 的状态,条件调用会导致顺序变化,状态错位。
追问:需要条件逻辑怎么办?→ 在 Hook 内部写条件,或者拆分组件。
【基础】useEffect 的执行和清理时机?
参考答案:在渲染提交到屏幕之后执行;依赖变化时,先执行上一次的清理函数,再执行新的 effect;组件卸载时执行清理。开发环境的严格模式会额外执行一次“挂载 → 卸载 → 挂载”来暴露缺少清理的问题。
追问:useLayoutEffect 有什么区别?→ 在 DOM 更新后、浏览器绘制前同步执行,用于测量布局,避免闪烁;会阻塞绘制,谨慎使用。
进阶
【进阶】setState 是同步还是异步的?
参考答案:调用后不会立即改变当前渲染中的值(状态是快照),更新会被批量处理并在之后重新渲染。React 18 起在事件、Promise、定时器中都会自动批量。依赖旧值的更新用函数式写法 setX(x => x + 1)。
追问:需要立即拿到更新后的 DOM 怎么办?→ 极少数情况可以用 flushSync,一般在 effect 中处理。
【进阶】React 和 Vue 的更新机制有什么区别?
参考答案:Vue 通过响应式系统精确追踪依赖,数据变化时只更新依赖它的组件;React 状态变化后从该组件开始重新执行渲染函数并比较,默认会渲染子树,靠 memo 等手段优化。Vue 的 setup 只执行一次,React 函数组件每次渲染都执行。
追问:哪种更好?→ 各有取舍:Vue 自动优化、心智负担小;React 模型简单(UI = f(state))、生态和并发特性丰富。
【进阶】服务端数据为什么不建议放在 Redux 里?
参考答案:服务端数据需要缓存、失效、后台刷新、重试、去重请求、分页等能力,自己在 Redux 中实现复杂且容易出错。TanStack Query 等库专门处理这些;全局 store 只放真正的客户端状态。
追问:TanStack Query 的 staleTime 和 gcTime 是什么?→ staleTime 决定数据多久后被视为过期(过期才会重新请求);gcTime 决定不再使用的缓存保留多久后被回收。
场景题
【场景题】设计一个长任务(Agent 生成报表)的前端界面,要注意什么?
参考答案:以服务端为准(任务 ID、刷新后恢复、幂等提交);useReducer 状态机;事件序号去重;重连时先取快照;失败区分可重试;取消等待后端确认;等待用户输入的交互。详见长任务界面场景。
追问:怎么测试?→ reducer 是纯函数,直接写单元测试覆盖各种事件序列;组件用 Testing Library 模拟事件订阅。
【场景题】搜索框输入时列表过滤很卡,怎么优化?
参考答案:输入框状态和列表过滤分离;用 useDeferredValue 让列表渲染延后,保证输入流畅;列表虚拟化;过滤计算 useMemo;数据量大时防抖或放到 Web Worker / 服务端。
追问:防抖和 useDeferredValue 的区别?→ 防抖固定延迟后才执行;useDeferredValue 由 React 调度,空闲时尽快渲染,可以被新的输入中断,不需要选择延迟时间。