最近帮几轮候选人做模拟面试,发现一个反复出现的问题:大家准备的react 面试题答案都“很标准”,但一被追问就发虚。尤其问到React 18的更新批处理机制、React和Vue路由到底差在哪、不同业务场景下怎么选型这些问题时,多数人只能背出结论,讲不清推导过程。这篇东西想把我在真实面试中被问过、也问过别人的那些问题串一遍,从React 18自动批处理的原理推导,到React Router和Vue Router的底层设计差异,再到React Native白屏这类实战坑该怎么在面试里谈,最后给出一份可以照着复盘自己项目的追问清单。如果你正在准备react面试,或者带过React项目但没系统梳理过底层逻辑,这篇文章应该能帮你把零散的知识点串成一条能扛住追问的线。
1. React 18的自动批处理机制:从一道送分题到送命题
1.1 批处理是什么,以及为什么React 18之前它“不完整”
批处理(Batching)这个概念,如果只背定义,那就是“React会将多个状态更新合并到一次渲染中执行”。但面试官真正想看的是,你有没有从渲染机制层面理解它为什么存在、边界在哪里。
先说为什么需要批处理。React的核心工作方式是“状态变化触发渲染”,这里的渲染指的是从虚拟DOM到真实DOM的更新过程。如果每次setState都立刻触发一次完整的渲染流程,那一个事件处理函数里连续调用三次setState,就会触发三次渲染。真实DOM的创建、对比、更新、布局、绘制,每一步都有成本。批处理做的事情,就是把同一个事件处理函数里、同一个同步执行过程中的多次状态更新攒起来,在事件结束后统一执行一次渲染。
React 18之前,这个机制有一个明显的边界漏洞:它只在React自身的事件系统里生效,比如onClick、onChange这些合成事件。一旦跳出React事件系统,跑到原生事件监听器、setTimeout、setInterval、Promise回调里,批处理就失效了。React 17及之前版本中,在这些场景里连续调用多个setState,React会老老实实每个都触发一次同步渲染。
这个问题的根因在于React旧版调度器的实现方式。React事件系统在处理完回调后,会主动调用一个内部方法来统一执行待处理的更新;而原生事件、定时器、异步回调走不到这条统一收口的路径,更新只能零零散散被处理掉。很多老项目里遇到的“在setTimeout里疯狂setState导致页面卡顿”,根源就在这里。
1.2 React 18的自动批处理到底改了什么
React 18发布时,自动批处理(Automatic Batching)是一个非常重要但又容易被一句话带过的更新。它的核心变化可以概括为:批处理不再依赖“是否在React事件系统中”,而是默认覆盖所有更新场景。
换成代码来看会更直接:
// React 18之前:setTimeout里三次更新会触发三次渲染 setTimeout(() => { setCount(c => c + 1); setFlag(f => !f); setName('react'); }, 100); // React 18:无论在哪里,同一个执行上下文内的多次更新都会被合并 setTimeout(() => { setCount(c => c + 1); setFlag(f => !f); setName('react'); }, 100); // 这里只触发一次渲染React 18的调度器在底层引入了更细粒度的更新优先级机制。每产生一次状态更新,React并不是立刻去执行渲染,而是先把这次更新以任务的形式放进调度队列,由调度器根据优先级决定什么时候、以什么顺序来处理这些更新。这个设计带来的直接好处是,无论是在什么异步环境里发起的更新,只要它们处于同一个“可中断的批处理窗口”内,就能被合并到一起执行。
这里想提醒一个容易被忽略的点:自动批处理并不是把时间上临近的所有更新都无条件合并。如果你在两个不同的异步回调里分别调用setState,这两个回调执行时间相差哪怕只有几毫秒,调度器也可能把它们当成两个独立的任务来处理,这件事在React 18的官方文档和设计讨论里有过明确说明,核心是“同一批同步代码里的更新会被合并,跨异步任务边界不一定能合并”。
1.3 面试追问链:从“会不会渲染几次”到“为什么能合并”
面试官如果只问“React 18自动批处理是什么”,那属于基础送分题。真正拉开差距的是下面这条追问链,你们可以自己试着一层层往下接:
第一个问题往往是:在React 18里,下面的代码会触发几次渲染?
function App() { const [count, setCount] = useState(0); const [flag, setFlag] = useState(false); const handleClick = () => { setCount(count + 1); setFlag(!flag); }; console.log('render'); return <button onClick={handleClick}>click</button>; }答案是一次。因为两次setState处于同一个onClick事件处理函数里,属于同一批同步代码。
接着面试官会改条件:如果在handleClick里套一个setTimeout呢?在React 18里还是一次,因为自动批处理已经覆盖了setTimeout场景。但React 17里是两次。这也是React 18升级时最直观的体验变化之一。
再往下,面试官可能会问:如果我在批处理的过程中想立即拿到更新后的state去做后续计算怎么办?React 18提供了一个flushSync方法,它能把传入回调里的状态更新从自动批处理中强制“踢”出来,让React同步执行更新。这个API的存在本身就说明了一个问题:自动批处理是一个默认策略,但React给了你打破默认策略的出口。能主动提到flushSync的候选人,至少说明他真的在项目里处理过“需要同步读取最新DOM状态”的场景,而不是只看了几篇源码解析。
最后还有一道高频追问:React 18为什么要费这么大力气去改批处理的覆盖范围?这时候如果只答“为了性能优化”,面试官会觉得很浅。更完整的回答应该包括两个层面:
- 用户体验层面:减少不必要的渲染次数能降低主线程的负担,让交互响应更快,尤其是在定时器、轮询、动画帧回调这类高频场景里,收益非常明显。
- 架构准备层面:React 18主推的并发特性(Concurrent Features)需要调度器能够随时中断、恢复、丢弃任务。如果状态更新还被绑定在“必须同步、必须立即执行”的旧模型里,并发渲染就是空谈。自动批处理把更新统一收口到调度器,本质上是在为并发渲染铺路。
能答到这个层面,这个问题基本就过关了。React的更新机制是一层套一层的,面试官想测试的就是你是否能把“事件机制——调度器——渲染器”这条链路串起来。
2. React和Vue路由差异:面试时不要只说“一个用配置,一个用组件”
2.1 路由问题的真相:API形态只是表象,底层模型差距才是重点
被问到“React和Vue的路由有什么差异”时,我听过最可惜的回答是“React Router是组件式的,Vue Router是配置式的”。这个说法单独拎出来不能算错,但它只描述了两者最表层的API风格差异,没有触及为什么会有这种差异,以及这种差异会带来什么实际影响。
先纠正一个常见误区。React Router从第4版开始走向“组件即路由”的设计思路,把Route、Link、Switch(新版叫Routes)这些概念封装成可渲染的组件,路由规则不再是集中式配置,而是散落在组件树的各个角落。Vue Router一直保留着“集中式路由配置表”的模式,路由规则定义在一个JavaScript对象里,组件只是配置表里的一个字段。
但这件事不能反过来理解成“React不能配置化、Vue不能组件化”。React Router的createBrowserRouter、useRoutes可以写出极近配置化的代码;Vue Router的RouterView、router-link本质上也是组件。所以API形态不是一个硬性壁垒,更重要的是两套路由方案在“如何把URL和UI层连接起来”这件事上的底层逻辑差异。
2.2 核心差异拆解:嵌套路由、匹配机制、导航守卫
嵌套路由的实现方式,是React Router和Vue Router之间最能体现设计思路差异的地方。
Vue Router的嵌套路由天然和嵌套组件绑定。路由配置表里的children字段,描述的不是简单的URL层级,而是Vue组件的父子关系。渲染时,每个层级对应一个RouterView,父级RouterView渲染出父组件,父组件内部的RouterView再根据子路由配置渲染下一层。这种“一个层级对应一个出口”的设计,优点非常直观:组件嵌套结构清晰,你看到路由配置就能准确推断出组件树长什么样。
React Router在v6版本里改用了Outlet作为子路由的出口。路由对象可以嵌套配置children,父路由渲染时,它的子路由会渲染在父组件中写的<Outlet />位置。React Router的嵌套不需要让子路由组件物理上“嵌”在父组件代码里,而是通过Outlet这个占位符在运行时动态决定渲染谁。这种解耦方式更灵活,组件树和路由结构不必一一对齐,但代价是,第一次接触的人需要先理解Outlet这个抽象概念,否则很容易困惑“子路由到底渲染到哪儿去了”。
匹配机制上两者也走的是不同的路。Vue Router的路径匹配基于一个精确度分层系统,它会对每条路由记录计算一个分数,路径越具体分数越高,遇到同级路由时使用最高匹配分。React Router v6的路径匹配算法则从“排名”角度切入,用动态分段、通配符、可选段的权重比较来决定谁更优。
导航守卫这方面,Vue Router有一组非常成熟的钩子函数体系,全局守卫beforeEach、beforeResolve、afterEach,路由级守卫beforeEnter,组件内守卫onBeforeRouteUpdate等等,是一个从路由开始匹配到组件确认完成的完整链路。React Router很长一段时间内没有官方内置的导航守卫,v6.4之后推出的loaders、action和useNavigation才提供了接近守卫的能力,但定位和含义跟Vue Router并不一样。需要强调一个事实:React Router v6.4之后的数据API改变了很多人对它的认知——目前很多react面试题里的对抗性和版本差距,来源往往是一个人的经验停留在React Router v5甚至更早。
2.3 一个必须知道的路由模式差异
React Router和Vue Router还有一层重要的差异容易被忽略,就是“路由到底管得多宽”。
Vue Router在Vue生态里的定位是“官方唯一指定路由”,和Vue的响应式系统深度耦合。路由变化会触发响应式依赖更新,组件里的$route对象会实时响应。React Router则只是React生态里众多选择之一,它并没有深入到React的状态管理里面去。react-router-dom的核心关注点是“URL和UI的映射关系”,至于路由状态要不要同步到Redux、Zustand、Jotai,完全取决于你自己怎么做。
面试时如果能把这条差异结合项目经验讲出来,比如“我们当时需要在路由变化时同步重置组件状态,React Router不会自动处理这件事,所以在包裹层写了一个监听location变化然后重置状态的逻辑”,面试官就会觉得你是真的踩过坑之后总结出来的,这种答法比背十篇React Router vs Vue Router对比文章都管用。
2.4 两种路由各自更适合什么业务场景
带着这些差异再回头看选型问题,就清楚了:
- 如果项目是标准后台管理系统,页面层级深、嵌套结构固定、权限模型复杂,Vue Router的集中式配置和成熟守卫体系能极大降低维护成本。路由表直接对应菜单权限表,守卫里做登录态校验和角色过滤也顺手。
- 如果项目是前台展示型页面、交互密度高、页面之间关联跳转复杂,或者需要在一个页面里频繁切换不同视图而不改变URL语义,React Router的组件化嵌套方式和
Outlet设计会更顺手——路由布点完全可以跟着组件树走,不绑死在配置表里。 - 如果团队里两种技术栈都有,且需要长期维护,最好的做法不是在某一个项目里硬套另一种风格的写法,而是遵守各自的路由实践约定,保持代码风格和团队心智模型的一致性。
2.5 切换场景里的常见坑:React Native的启动白屏
由于搜索词里多次出现“react native 启动白屏”,可以顺便提一下,如果你做过React Native项目,路由和导航的选择会直接影响启动白屏问题的定位难度。RN导航里很多团队用React Navigation,它借鉴了React Router的声明式写法,但底层是原生的原生栈。所谓“启动白屏”,简单来说就是首帧渲染之前,原生容器已经展示,但JavaScript端还没有把内容渲染出来。这在React Native里非常常见。
需要理解的是,这个问题之所以被反复讨论,是因为它涉及RN应用启动的完整链路。在React Native里,App启动后首先要做的不是渲染页面,而是启动一个独立的JavaScript引擎。对于旧架构的RN,App首次启动时需要先加载打包后的JavaScript代码,创建一个ReactContext,这个过程中原生UI容器已经创建并显示,但React组件还没有完成挂载。用户看到的就是一块白屏。如果你用了react-native-screens这类基于原生导航容器的库,它的启动页面切换可能还会再做一次原生View的预创建,处理不当也会加深白屏观感。
React Native的常见优化手段包括:
- 把启动白屏的容器背景色设置成接近首屏主色调,视觉上减少“白”的时间感。从用户看,这个黑或灰比白更可接受。
- 减少启动时需要加载的JS Bundle体积。对业务代码做模块化拆分,只加载启动路由所需的最小模块。
- 在原生侧做预创建内容。例如,在需要的时候允许“先显示一张原生启动图”,直到JS渲染完成再切换到React内容。
- 用Hermes替代JavaScriptCore。Hermes的启动解析速度比JSC快不少,实测冷启动白屏时间有明显缩短。
面试时谈到RN白屏,最忌讳的是直接甩一句“用Hermes就能解决”。更好的表达是把你做过的具体优化动作和它对启动链路的哪个环节产生影响讲清楚。这样才能体现你的项目经验不是“知道名词”,而是真的上过一线。
3. 不同业务场景下,React和Vue项目到底该怎么选择
3.1 选择逻辑的起点,不应该是“哪个火”
很多人对React/Vue的选型争论,容易陷入“谁更先进谁更火”的站队。如果只是个人学习,多学一个没坏处;但在实际项目里,选型必须回到成本和场景里去判断。两个框架能同时在开发者社区长期共存,说明各自都有不可替代的生态位,这是选题的核心逻辑。
老生常谈的一点是:招人难度和团队熟悉度是选型中绕不开的成本。这个因素我见过的很多技术决策报告中反而被最小化,但实际落地时最先出问题的往往就是这里——一个团队没人Vue写得熟,却因为某篇文章说React生态好就强行切,交付和质量受影响是大概率事件。“按团队熟悉度选型”看起来不酷,但在中小团队和长期项目中是最稳的决策方式。
不过这里有一个必须提到的坑:不能因为“团队熟”就无脑锁死某个技术栈,而忽略业务形态本身对技术框架的适配性。
3.2 用“业务复杂度”来找切入点:适合React的场景
React的并发渲染、Fiber架构、庞大的自定义生态,使得它在以下场景更有优势:
- 页面交互密集的SaaS类应用、数据分析看板、在线文档编辑器这类核心操作对渲染效率要求极高的场景。React的可中断渲染机制可以保证高优先级操作不被大量后台更新阻塞,实测在超大表格、实时协作这类场景下体验提升明显。
- 对“渲染可控性”有额外要求的场景。React的“UI是state的函数”这个心智模型,让状态驱动的复杂UI逻辑更容易被推导和稳定复现。
- 需要共用一套代码逻辑到React Native移动端的场景,Web端和移动端复用函数逻辑和状态管理心智,能明显降低维护成本。
- 社区方案多样性很重要的项目。React的可组合性意味着你可以自由选择状态管理方案(Redux/Zustand/Jotai)、路由方案、数据请求方案,不受官方全家桶的限制。
3.3 用“业务复杂度”来找切入点:适合Vue的场景
Vue适合的场景,我的判断是这样的:
- 中小型后台系统、工具型页面、内容型站点。Vue的渐进式架构,意味着一个简单页面可以不用引入全家桶,一个
createApp就能跑起来,做成多页应用也更灵活。 - 团队稳定性优先、希望框架给出更多“默认规范”的场景。Vue官方提供的配套方案(Vue Router + Pinia + Vite)已经被验证在大量中后台项目里能平滑协作,选型时不需要做很多取舍讨论。
- 需要快速上手的团队。Vue的模板语法对从HTML/jQuery转过来的开发人员更友好,可以显著降低团队入门成本。
3.4 同样是技术选型,React还是Vue在具体语境下的特殊优势
看热搜词里提到“react和vue路由差异,在不同业务场景下如何选择”,搜索意图明显是选型对比。我见到的选型讨论里,最容易被忽略的是框架对不同应用结构的契合度。
React本身对“前端应用应该怎么组织”约束很少。它不要求你使用某个状态管理库,不要求你从某个脚手架启动,也很少规定代码应该怎么分层。这个自由度在大型项目里是双刃剑,架构能力强的团队可以把React项目组织得极其漂亮,代码清晰度高;但如果团队缺少统一的架构规范和严格的Code Review,React项目的代码风格会逐渐发散,最终变成“一个项目一种写法”。
Vue的官方风格指南、单文件组件、组合式API的方向性约束,其实给团队提供了一个默认的“最佳实践锚点”。新成员通过读官方文档就能了解多数项目的代码组织方式,项目管理的隐性沟通成本会小很多。我见过很多大厂内部维护的“Vue项目最佳实践”文档,里边的内容大多是在官方约束之上再补充规范,这说明Vue的“默认主见”其实能充当一部分架构决策的角色。
面试中谈到“不同业务场景如何选择”时,不用急着给出一个二选一的答案。把选择的多维度描述清楚,甚至能倒推出不同场景下的结论,面试官会给你加很多分。
3.5 面试里可以用到的选型回答框架
分享一个我在模拟面试里经常建议候选人使用的框架,按这个思路组织,能体现你既懂技术又懂项目管理:
一是场景维度——项目是什么类型,ToC流量型还是ToB内部型,交互复杂度大概在什么水平,需要支持的浏览器/平台范围是怎样的?
二是团队维度——团队现有技术栈是什么,主力开发者的框架熟悉程度如何,有没有意愿储备多技术栈的成员?
三是长期维护维度——项目的规划生命周期是多久,未来会不会有大量功能迭代、人员更替,是否要考虑跨端复用?
四是生态取舍维度——项目需要哪些核心支撑库,这些库在对应框架生态里的成熟度和维护活跃度如何?
把这四条掰开讲完,面试官能顺畅地判断出你选型的依据是实际业务的约束条件,而不是流于表面的“React比Vue强”。
4. React学习与面试准备的底层路线:别把“会写组件”当成“会React”
4.1 react-router、react-dom、fiber与React“能力分层”
准备React面试最常见的一个误区,是把React简单等同于“组件写法+常用Hooks”。如果你在简历上写“熟练使用React”,却在面试中被问到“React Router的history和search参数监听原理是什么”“React为什么要引入Fiber”“React事件系统为什么是合成事件”时大脑一片空白,那你的“熟练”就要被打一个问号。
我建议所有准备React面试的人都把React技术栈拆成几个能力层来复盘,这样能知道哪些知识必须补:
- API使用层:JSX、组件化、props、state、Hooks、Context。这是最基础的,大多数日常工作用到的主要在这一层。
- 渲染机制层:虚拟DOM实现、diff算法细节、render commit流程、Fiber架构思想、并发渲染、批处理机制。这一层开始拉开差距。
- 生态层:React Router的路由历史和匹配机制、状态管理库的原理、Next.js的SSR/SSG、React Native的渲染链路。这些是React真正落地于项目的关键。
- 性能与排错层:React DevTools的分析能力、Profiler的使用、脱离重新渲染的方法、React Native白屏排查、SSR水合不匹配等实战问题的排查思路。能看到实际崩溃或卡顿的原因,才算把React吃透。
分层复盘还有一个额外收益:你知道面试官接下来要往哪个方向追问了。凡是简历上写了“熟悉React”,对方大概率会从第一层往上快速提问,你必须能在第二层给出有实质内容的回答——比如对Fiber的解释如果只会背“Fiber是一个链表结构”,大概撑不过下一个“为什么需要链表”的追问。
4.2 React 18版本更新在面试中的正确打开方式
搜索词里反复出现“react 18 的更新批处理机制”,说明这仍是高频考点。除了前面讲到的基础概念,还有两个方向值得展开理解。
第一点是React 18的startTransition与批处理的关系。startTransition标记的更新是低优先级更新,可以让出主线程给高优先级更新。它和自动批处理的底层机制有配合:React调度器会优先处理紧急任务,有剩余时间再处理transition更新,如果中间一直有紧急任务,transition更新会被延迟或中断。面试中能聊到这一层,说明你已经理解了React 18并发特性的主心骨:渲染不再是必须一口气完成的“全有或全无”操作。
第二点是React 19的走向。近两年React 19发布了稳定版,它带来了一些新特性,比如useOptimistic优化UI更新、useActionState简化表单处理、useFormStatus下放到表单组件。React 19在服务端组件和Actions上做出了明显的方向性强调,把Server/Client的边界从约定提升到了框架强约束。准备面试时,如果能在被问到React未来方向时讲出“React Router、React Server Components、Actions在数据流与状态更新上的重新整合计划”,会比只背18版本特性更能让人记住。
4.3 怎么用“面经、AI Agent、项目复盘”来构建你自己的React知识库
热搜词里有一类“react面经”、“react学习”和“aiagent react”,实际上暗示了当前React面试准备的主要来源。这里想多说一句,面经可以作为查漏补缺的题目集,但不能当成标准答案库。
React相关面试题最忌讳死记硬背。原因是React的更新迭代很快,比如React Router的API在v4/v6之间经历了巨大的变化,Hooks也才出现几年,React 18的自动批处理把旧的异步更新行为又改了一遍。如果你背的是某个时间点下的“标准答案”,而面试官只追问了一个当时版本尚未支持的API的细节,你立刻就会在概念层次上自乱阵脚。
AI Agent在这个话题里能帮上什么忙?现在很多人在用AI辅助刷题或模拟面试,它更擅长帮你发散思考,而不是直接给结论。你可以让AI扮演面试官,连续追问“为什么”;或者把你自己项目的关键逻辑拿出来,快速生成多个可能的追问方向;还可以拿一段踩坑经历,让AI帮你想清楚这个问题的根因要如何直白地讲给面试官听。
我见过很多人的项目经验只是“使用了React框架开发了某个系统”,问“遇到什么难点”时讲的全是业务需求复杂。这时候就要有复盘意识:你在项目里遇到的性能问题诊断过程、某个React Native白屏的排查流程、对React与Vue路由在同一个技术产品里的深度体验,稍微加工就能变成一条高质量的面试故事线。
拿“启动白屏”来说——我前面提到React Native不少团队都碰到过这类体验问题,但你有没有在讲述中把症状一开始误判为网络加载慢、去掉loading之后找不到白屏根源、后来用Hermes才解决的完整链路讲出来?面试官想听的从来不仅是修复方式,更是你是怎样从现象出发做逆向推理的。能清楚复盘一个问题从发现到根因到解决的完整历程,这是极有说服力的实战证据。
4.4 准备React项目部署与展示时,别忘了“GitHub仓库怎么建”这种表面问题
热搜词里有一条“react项目创建github仓库”,看似偏新手,但很多人在面试前准备作品集时会被这个问题卡住。分享一个最简单又能复用很久的流程。
如果你已经用Vite创建了一个React项目,命令行操作可以参考:
# 1. 在GitHub新建一个空仓库,不要勾选README # 2. 本地项目初始化并关联远程仓库 git init git add . git commit -m "feat: initialize react project" git branch -M main git remote add origin https://github.com/<你的用户名>/<仓库名>.git git push -u origin main部署到GitHub Pages时的注意事项:
- 注意Vite打包的
base路径需要设置成你的仓库名,否则部署后静态资源引用会出现404。 - 如果使用HashRouter可以避免BrowserRouter在GitHub Pages下刷新子路由404的问题,但这会牺牲URL的干净语义,这个取舍需要根据项目性质来判断。
- 部署流程上,可以先配置GitHub Actions把
npm run build产物发布到gh-pages分支。
这件事情虽然不涉及React面试的核心,但实际被问到的概率不低。很多会让候选人现场打开自己的仓库页面来介绍项目。一个干净且有清晰首页说明、分支策略和提交历史的仓库,比几百行代码更能说明你是一个工程习惯好、能直接进入协作状态的React开发者。
5. React领域高频追问链与实战准备清单
5.1 十个高频问答里的底层逻辑辨析清单
从“react 面试”“react面经”里抽出十个常考点,整理成“一道题一个底层逻辑”的表格,供面试前速查。这里列出的不是需要逐字背的答案,而是让每个问题在你大脑里成一个体系时想清的方向。
| 面试题 | 核心底层逻辑 | 容易踩的坑 |
|---|---|---|
| React 18自动批处理是什么? | 调度器对更新任务按优先级统一收口,在可中断窗口内合并渲染 | 误以为所有异步场景都无条件批量合并 |
| 为什么要用Fiber? | 使渲染过程可中断/恢复/优先级调度,解决旧的递归协调栈占主线程的问题 | 只背“链表”,不讲清可中断的意义 |
| Hooks为什么不能在条件语句里调用? | Hooks依赖固定的调用顺序保证状态与fiber节点的匹配 | 只说“官方规则”,讲不出底层原因 |
| React合成事件和原生事件有什么区别? | 合成事件统一绑在根容器上做事件委托,实现跨浏览器一致性并配合Fiber架构 | 以为React事件完全无法与原生事件混用 |
| useEffect和useLayoutEffect适合什么场景? | useEffect异步执行不阻塞绘制;useLayoutEffect同步执行阻塞绘制但能避免闪烁 | 统一当“生命周期”背而忽略副作用执行时机细节 |
| 为什么要在React中避免使用index作key? | key是节点复用的标识,用index会导致列表增删时组件内部状态错位 | 拿“不做列表操作”来辩护,但diff算法仍需逐个插入 |
| 中间态渲染在React里如何控制? | loading需要被显式建模,将异步状态纳入组件状态渲染;React 18可用useTransition实现过渡UI | 忽略渲染确定性,在render里直接写异步请求副作用 |
| React Router里BrowserRouter与HashRouter差异是什么? | 两者对应history和hash两套路由模式,影响URL语义、服务端配置和爬虫收录 | 只背“一个好看一个不好看” |
| 状态管理怎么选型? | 看数据流复杂度以及是否需要跨组件共享/持久化/服务端缓存,Zustand/Redux/Jotai各有适用边界 | 逢项目就上Redux,导致模板代码过多 |
| React Native白屏如何排查? | 启动链路从引擎加载到Bundle执行到原生渲染,优化点分散在引擎选择、Bundle拆分、容器预创建等处 | 只背“用Hermes”单一答案 |
5.2 一套可以在任何项目演示时复用的“面试项目复盘框架”
如果要给一个万能的准备React面试的建议,我不会让大家去背更多题,而是建议在面试前一天,认真把你自己的项目用下面这个框架复盘一遍。
这个框架我自己反复用过,也推荐过很多准备面试的朋友,效果都很好:
- 第一步:项目定位。一句话说清楚做了什么,给谁用,解决什么问题。目标需要让你说完后让面试官对项目有画面感,而不是只能记住“一个后台管理系统”。
- 第二步:技术决策。为什么用React而不是别的框架,为什么用这个路由方案,为什么用这个状态管理库。关键点是每个技术选择都尽量对应到业务约束,而不是“大家都用”。
- 第三步:开发链路。项目从搭建到上线的完整链路长什么样,用没用CI/CD,部署方式是什么,有没有容器化,域名证书流程是否亲历过。团队开发的项目还可以讲清你在其中具体负责了哪一段。
- 第四步:难点深挖。选一个你亲手调过的最难问题,讲清现象、猜测、验证、根因、修复、复盘这一个完整过程。宁可是一个很“小”的问题——只要链路完整、思路清晰,就比讲一个含糊的大系统更让人信服。
- 第五步:反思与延伸。如果时间倒流你会用什么不一样的方案,这个问题在其他项目场景里还可能出现怎样的变种,下次如何更早避免。
5.3 快速验证自己React水平是否合格的一道自测题
作为这篇文章的收尾,分享一道很适合用来验证自己对React理解水平的自测题。如果你看到题目就能顺畅地讲出答案和原因,那你的React基本功算是靠谱的;如果卡壳,说明还需要补课。
这道题是:为什么useState返回的更新函数,在React 18自动批处理机制下,不在React事件系统里的异步函数里也能合并更新?请说明它的实现原理,并顺带指出在哪些边界场景仍然无法被批处理覆盖。
答出“调度器统一收集”“Fiber调度优先级窗口”“update队列处理时机”这些,可以算过关;能进一步讲出“跨异步任务边界可能无法合并”等边界情况,基本就已经领先大多数候选人。
准备任何技术面试,最扎实的心态就是:与其在大量“你会不会背题”中焦虑,不如以项目复盘为抓手,把每个技术细节在自己的手指上过一遍。React并不是一个需要靠背诵来体现能力的框架,它能走多远,取决于你去用它解决多么复杂的问题。祝你在模拟面试和真实面试中,都能把心中的React讲得更清晰、更有底气。