Skip to content

React 高频面试题答案速查

这页只整理 React 相关的高频答案。回答时建议先给结论,再补项目场景。

React 是什么?

React 是用于构建用户界面的 JavaScript 库。它的核心思想是组件化和声明式 UI。开发者描述界面应该是什么样,React 根据状态变化更新真实 DOM。

项目化补充:React 本身只负责 UI 层,路由、请求、状态管理、构建工具通常由生态方案组合完成。

JSX 是什么?

JSX 是 JavaScript 的语法扩展,可以在 JS/TS 中描述 UI。它不是 HTML 字符串,最终会被编译成 React 元素。

项目化补充:JSX 中使用 className,事件使用驼峰,比如 onClick

state 和 props 有什么区别?

props 是父组件传入的数据,子组件不应该直接修改。state 是组件内部维护的数据,更新 state 会触发组件重新渲染。

项目化补充:如果多个组件共享状态,先考虑状态提升;跨页面共享再考虑全局状态库。

React 的渲染流程是什么?

React 更新可以分为 Trigger、Render、Commit。状态变化触发渲染,React 调用组件函数计算新的 UI 描述,然后把变化提交到 DOM。副作用通常在 commit 后通过 effect 执行。

项目化补充:render 阶段应该保持纯粹,不要在渲染中请求接口或直接修改外部状态。

React 中 state 为什么像快照?

组件每次渲染都会拿到当前这次渲染对应的 state。调用 setState 不会立刻改变当前函数里的 state 变量,而是触发下一次渲染。

项目化补充:如果连续更新依赖上一次状态,应该使用函数式更新。

tsx
setCount((count) => count + 1)

为什么 Hooks 不能写在条件或循环里?

Hooks 依赖稳定的调用顺序来对应内部状态。如果写在条件或循环中,每次渲染调用顺序可能变化,React 就无法正确匹配 Hook 状态。

项目化补充:条件逻辑可以写在 Hook 内部,而不是条件性调用 Hook。

useState 和 useReducer 怎么选?

useState 适合简单独立状态。useReducer 适合复杂状态,尤其是多个状态变化互相关联,或者更新逻辑需要集中管理时。

项目化补充:复杂表单、状态机、多个操作影响同一对象时,可以考虑 useReducer

useEffect 是做什么的?

useEffect 用来让组件和外部系统同步,比如请求接口、订阅事件、操作浏览器 API、建立 WebSocket、同步第三方库实例。

项目化补充:能在事件里完成的逻辑,不一定要放进 effect。不要把 effect 当成万能监听器。

useEffect 的依赖数组怎么理解?

依赖数组表示 effect 依赖哪些响应式值。没有依赖数组会每次渲染后执行,空数组通常只在挂载后执行一次,有依赖则依赖变化后执行。

项目化补充:不要为了“只执行一次”故意漏依赖,容易造成旧值和隐藏 bug。

useEffect 和 useLayoutEffect 有什么区别?

useEffect 在浏览器绘制后执行,适合请求、订阅、日志等大多数副作用。useLayoutEffect 在浏览器绘制前同步执行,适合读取布局并立即修正 DOM,避免闪烁。

项目化补充:useLayoutEffect 会阻塞绘制,不应该滥用。

useRef 有什么作用?

useRef 可以保存跨渲染不变的可变值,修改它不会触发重新渲染。常见用途是获取 DOM、保存定时器 ID、保存第三方实例、记录上一次的值。

项目化补充:需要驱动 UI 更新用 state,只是保存可变引用用 ref。

自定义 Hook 解决什么问题?

自定义 Hook 用来复用状态逻辑,而不是复用 UI。它通常以 use 开头,可以封装请求、表单、弹窗、权限、订阅等逻辑。

项目化补充:如果多个页面都有相同的 loading、请求、错误处理逻辑,可以抽成自定义 Hook。

常见闭包陷阱是什么?

事件、定时器、异步回调中拿到的可能是某次渲染时的旧 state。解决方式包括正确填写依赖数组、使用函数式更新或用 ref 保存最新值。

项目化补充:定时器里打印的 count 一直不变,就是典型闭包旧值问题。

useMemo 和 useCallback 有什么区别?

useMemo 缓存计算结果,useCallback 缓存函数引用。useCallback(fn, deps) 可以理解成 useMemo(() => fn, deps)

项目化补充:它们不是越多越好,只有昂贵计算或配合 memo 保持引用稳定时才更有价值。

React.memo 为什么有时没效果?

React.memo 做的是 props 浅比较。如果父组件每次传入新的对象、数组或函数,即使内容相同,引用也不同,memo 仍然会重新渲染。

项目化补充:传给 memo 子组件的对象用 useMemo,函数用 useCallback,或者把常量移到组件外部。

Context 和 Redux 有什么区别?

Context 是 React 内置的跨层级传值能力,解决 props 透传。Redux 是状态管理方案,提供更清晰的数据流、调试、中间件和状态追踪。

项目化补充:主题、语言、当前用户可以用 Context;复杂业务状态、多人协作维护的大型应用可以考虑状态库。

受控组件和非受控组件有什么区别?

受控组件的表单值由 React state 控制;非受控组件的值由 DOM 自己维护,React 通过 ref 读取。

项目化补充:复杂表单、实时校验适合受控或表单库;文件上传、只在提交时读取的简单输入可以用非受控。

React 项目首屏慢怎么优化?

先定位资源、接口、JS 执行和渲染瓶颈。常见优化包括路由懒加载、React.lazySuspense、拆包、图片懒加载、减少首屏依赖、接口并行。

项目化补充:后台系统通常先做路由级拆包;内容型页面可以考虑 SSR 或 SSG。

大列表卡顿怎么优化?

可以分页、虚拟列表、懒加载,减少列表项复杂度,保持 key 稳定,避免给列表项传入不稳定 props。

项目化补充:如果一次渲染几千个 DOM 节点,再多 memo 也不如虚拟列表直接减少 DOM 数量有效。

Built with VitePress and GitHub Pages.