模块五 · AI 协作与表达
面试表达:把 React 讲成工程判断
面试不是背 API,而是展示判断。这一节给出"结论—机制—取舍—验证"的表达骨架、五个高频题的答法,以及项目案例与追问应对。
读完这一节,你能做到
- 用四步结构回答原理题,而不是背结论。
- 把 Hooks、渲染、Fiber、性能、状态五个高频题讲到点上。
- 用项目案例讲清一次技术决策与代价。
- 应对"为什么不用 Vue/如果重来"这类追问。
一、四步表达骨架
结论(一句话判断)
→ 机制(底层怎么实现)
→ 取舍(为什么这样设计,代价是什么)
→ 验证(怎么证明有效)
示例:问"为什么 Hooks 不能条件调用"。
- 结论:因为 Hooks 靠调用顺序定位状态。
- 机制:每个 Fiber 上有一条 Hooks 链表,第 n 次调用对应第 n 个节点。
- 取舍:规则限制写法,换来更简单的状态复用与更小的运行时开销。
- 验证:条件调用会让后续 Hook 错位,报 "Rendered fewer hooks than expected"。
二、五个高频题
1. setState 是同步还是异步
"调用是同步的,渲染是异步批量的。setState 只是把更新入队并调度,当前闭包里读到的仍是旧值;需要基于旧值更新时用函数式写法。"
2. useEffect 与 useLayoutEffect
"都是同步外部系统。useLayoutEffect 在 DOM 更新后、绘制前同步执行,适合读取布局;useEffect 在绘制后执行,适合请求与订阅。用错会导致闪烁或阻塞。"
3. 为什么 React 需要 key
"key 是节点身份。没有 key 时按位置复用,插入/删除会导致状态错位;用稳定 id 才能让 React 正确复用或重建。"
4. Fiber 解决了什么
"把递归渲染拆成可中断的工作单元,配合双缓冲与 Lane 优先级,让高优先级更新先执行,输入不卡。"
5. 怎么做性能优化
"先测量,再按'减少渲染范围 → 减少单次工作量 → 减少 DOM 数量'的顺序优化。常用手段是状态下放、children 组合、memo、虚拟列表;每项都要有前后对比。"
三、项目案例模板
背景:业务、规模、你的角色
问题:具体指标(首屏 4s、列表 2,000 行卡顿)
动作:为什么选这个方案,排除了哪些
结果:指标变化 + 代价
反思:如果重做会怎么改
不要只说"用了虚拟列表",要说"2,000 行列表滚动 18fps,虚拟滚动后 55fps,代价是不定高需要测量"。
四、追问应对
| 追问 | 回答骨架 |
|---|---|
| 为什么不用 Vue? | 团队栈、生态、开发效率,讲取舍不拉踩 |
| memo 为什么没生效? | props 是否每次新建、比较是否浅、children 是否稳定 |
| 如果数据量再大 10 倍? | 分页/虚拟滚动/服务端聚合,先算瓶颈 |
| 这个优化真的有效吗? | 基线、单变量、前后对比 |
| 看过源码吗? | 讲一个具体模块(如 Fiber 的 beginWork),不要泛泛而谈 |
五、常见坑
- 只背结论,讲不出机制。
- 把"setState 是异步的"说成"React 有个定时器"。
- 案例只有动作,没有指标与代价。
- 遇到不会的硬编,不如说"这块我没深挖,我的理解是……"。
- 贬低其他框架来抬高自己。
六、动手任务:自写 → AI 写 → 对比 → 取舍
这一步的"AI 写"是写答案,不是写代码:让 AI 用同一套骨架答一遍,你负责挑出它哪里在背结论。
① 自己写
选一个你做过的页面,用四步结构讲清一次性能优化,要求:
- 至少两个指标的前后对比。
- 至少一个"代价"或"没做好的地方"。
- 结尾给出"如果重做会怎么改"。
② 让 AI 写同一题
把同一道题交给 AI:用一个真实项目回答"你怎么做 React 性能优化",要求结论、机制、取舍、验证四段,并给出具体数字。
③ 对比
| 维度 | 我的版本 | AI 版本 | 差异说明 |
|---|---|---|---|
| 有没有具体指标 | |||
| 机制讲到哪一层 | |||
| 有没有代价与失败 | |||
| 追问一层会不会断 |
④ 说取舍
- AI 的答案里,哪句是正确的空话,一追问就塌?
- 它缺的那部分,是不是恰好是你的项目经验值钱的地方?
- 如果只能保留三段,你留哪三段?
七、自测
- 四步表达骨架是什么?
- setState 的"异步"具体指什么?
- key 的作用是什么?
- Fiber 的两个关键能力是什么?
- 性能优化的三步顺序是什么?
参考答案要点:结论/机制/取舍/验证;渲染批量调度;节点身份;可中断与优先级;缩小范围→减少工作量→减少 DOM。
附:五个追问的完整答法
问:setState 一定是异步的吗? 答:调用是同步的,渲染是批量的。React 18 起,事件、Promise、定时器里的更新都会批处理;需要同步读 DOM 时用 flushSync,但会牺牲批处理。
问:useMemo 能替代 useCallback 吗? 答:不能。useMemo 缓存值,useCallback 缓存函数;缓存函数也可以用 useMemo 返回函数,但语义不如 useCallback 清晰。
问:为什么 props 变了子组件不一定重渲染? 答:如果子组件被 memo 包裹且 props 浅比较相等,就会跳过。反过来,props 没变也可能重渲染——父组件渲染时,未 memo 的子组件都会跟着渲染。
问:Fiber 一定比栈调和快吗? 答:不一定。Fiber 的收益是可中断与优先级,不是单次渲染速度;它反而带来额外的链表操作开销。
问:你项目里最难的问题是什么? 答:讲现象、排查、假设、验证、结果、代价。不要讲“用了什么框架”。
附:如何讲源码而不翻车
- 只讲你读过的模块,比如
beginWork、completeWork、dispatchSetState。 - 先讲设计意图,再讲实现,最后讲边界。
- 不确定就说“这块我没读到”,比编造更加分。
附:面试准备清单
- 三个案例:性能、架构、失败
- 每个案例都能说出指标与代价
- 能手写一个 20 行的 useState
- 能解释一次 setState 到 DOM 的完整链路
- 准备两个反问问题
附:面试节奏
原理题控制在 2-3 分钟:先结论,再机制,再一句取舍。项目题 3-5 分钟:背景一句、问题一句、动作三句、结果一句、反思一句。被打断就顺着追问走,不要念稿。
如果对方连续追问细节,说明他在验证你是否真做过;这时给具体数字与代价,比背概念有效。
附:三个不要
不要背术语、不要把所有成绩归因于自己、不要讲没有数据的“大幅提升”。讲清判断与代价,比数字更重要。准备好两个失败案例,比十个成功案例更能证明水平。
附:反问的两个问题
- 团队目前最大的技术痛点是什么?
- 这个岗位前三个月最重要的目标是什么?
不要问“加不加班”“用什么框架”这类可以提前查到的信息。先把结论说清楚,机制讲一层就够。一句结论胜过长篇背景。
配套题目
★ 越多越该先背;点题目可看完整答案与深入版。
- ★★★★★ 为什么 Hooks 不能写在条件语句或循环里?
- ★★★★☆ useEffect 的执行时机是什么?和 useLayoutEffect 怎么选?
- ★★★★☆ 什么是 Fiber 双缓存?它解决了什么问题?
- ★★★★★ React 中如何避免不必要的重渲染?
- ★★★★☆ React 中如何设计权限、表单和组件库?
提示:读完可以顺手做几道对应题目,检验是否真的理解