React高频面试题参考答案
1. React 中 state 和 props 有什么区别?
- 核心区别: state 是组件内部私有的可变数据,由组件自身修改; props 是父组件传递给子组件的只读数据,子组件不能直接修改。
- 数据流向: props 是“自上而下”的单向流, state 仅在组件内部循环更新。
2. React 的生命周期分为哪些阶段?每个阶段可以做什么?
React 类组件生命周期分3个核心阶段,Hooks 中用 useEffect 覆盖大部分场景:
1. 挂载阶段:组件首次渲染到DOM,仅执行1次。
- constructor :初始化 state 、绑定事件this。
- render :返回JSX,不允许执行副作用。
- componentDidMount :执行DOM操作、发起网络请求、订阅事件。
2. 更新阶段: props 或 state 变化时触发,可多次执行。
- shouldComponentUpdate :返回布尔值,决定是否继续更新(优化性能)。
- render :重新渲染JSX。
- componentDidUpdate :更新后操作DOM、根据旧值做逻辑处理(需判断避免死循环)。
3. 卸载阶段:组件从DOM移除,仅执行1次。
- componentWillUnmount :清除定时器、取消网络请求、解绑事件订阅。
3. useState 和 useEffect 的工作原理是什么?
- useState:本质是“状态钩子”,调用时会创建独立的状态单元,通过闭包保存每次渲染的状态值;更新状态时(如 setCount ),会触发组件重新渲染,并传入新的状态值。
- useEffect:本质是“副作用钩子”,用于处理组件渲染后的副作用(如请求、DOM操作)。它会在组件渲染完成后执行,第二个参数(依赖数组)决定执行时机:空数组仅执行1次,无数组每次渲染都执行,有特定依赖则依赖变化时执行;返回的函数会在组件卸载或下次副作用执行前清除旧副作用。
4. React 中的虚拟 DOM 是什么?它的优势是什么?
- 虚拟 DOM(Virtual DOM):是 React 内部维护的、用 JavaScript 对象表示的DOM树副本,它映射了真实DOM的结构和属性,不直接操作浏览器DOM。
- 核心优势:
- 减少真实DOM操作:通过“Diff算法”对比更新前后的虚拟DOM,只把差异部分同步到真实DOM,避免全量重绘。
- 跨平台能力:虚拟DOM是JS对象,可适配不同平台(如React Native将其转为原生组件),不依赖浏览器DOM API。
5. 什么是 React Fiber?它解决了什么问题?
- React Fiber:是 React 16 重构的协调(Reconciliation)引擎,本质是把“递归更新”拆成“可中断、可恢复的小任务单元”,类似“进程调度”。
- 解决的问题:旧版 React 用递归处理组件更新,过程不可中断,若组件树复杂,会占用主线程过久,导致页面卡顿、掉帧(如无法响应点击、滚动);Fiber 可暂停、恢复任务,优先执行用户交互等高频任务,提升页面流畅度。
6. 如何优化 React 应用的性能?
- 减少不必要渲染:用 React.memo 缓存组件(避免父组件更新导致无props变化的子组件重渲染), useMemo 缓存计算结果, useCallback 缓存事件函数(避免传递新函数触发子组件重渲染)。
- 优化渲染内容:长列表用“虚拟列表”(如 react-window ),只渲染可视区域内容;避免在 render 中创建函数、对象(会导致每次渲染生成新引用)。
- 代码分割与懒加载:用 React.lazy + Suspense 实现组件懒加载,按路由或功能拆分代码包,减少初始加载体积。
- 减少副作用开销: useEffect 依赖数组精准设置,避免无效执行;及时清除定时器、订阅等副作用。
7. React 中的事件系统与原生 DOM 事件有什么区别?
- 事件类型:React 事件是合成事件(SyntheticEvent),是对原生事件的封装,统一了浏览器兼容性(如 onClick 对应原生 click ,无需处理浏览器前缀)。
- 事件委托:React 事件不直接绑定在DOM元素上,而是委托到根节点(document),通过事件冒泡统一处理,减少内存开销。
- 事件处理:合成事件的 e.stopPropagation() 只能阻止合成事件内部冒泡,无法阻止原生事件冒泡;若要阻止原生冒泡,需用 e.nativeEvent.stopImmediatePropagation() 。
8. 什么是 Context API?它的使用场景和局限性是什么?
- Context API:是 React 内置的跨层级状态共享方案,可跳过中间组件,直接在父组件与深层子组件间传递数据(如主题、用户登录状态)。
- 使用场景:共享“全局且变化不频繁”的数据,如App主题、语言设置、用户身份信息。
- 局限性:
- 无法优化重渲染:若 Context 数据更新,所有消费该 Context 的组件都会强制重渲染,即使只用到其中部分数据(需配合 useMemo 手动优化)。
- 不适合复杂状态管理:无状态更新追踪、异步处理能力,复杂场景(如多组件修改同一状态)更适合 Redux、Zustand 等库。
9. Redux 的工作原理是什么?中间件的作用是什么?
- Redux 工作原理:基于“单向数据流”,核心由3部分组成:
1. Store:存储全局状态的唯一容器,通过 createStore 创建。
2. Action:描述状态变化的“指令”(如 { type: 'ADD_COUNT', payload: 1 } ),只能是普通对象,由 dispatch 触发。
3. Reducer:纯函数,接收旧 state 和 action ,返回新 state ( (state, action) => newState ),不允许修改原state、执行副作用。
- 流程:组件 dispatch(action) → Reducer 计算新state → Store 更新 → 订阅 Store 的组件感知状态变化并重新渲染。
- 中间件的作用:Redux 原生只能处理同步 Action,中间件(如 redux-thunk 、 redux-saga )用于扩展 dispatch 能力,支持处理异步逻辑(如发起网络请求后再更新状态)、日志打印、错误捕获等。
10. React Router 的实现原理是什么?
React Router 分 HashRouter 和 BrowserRouter,核心是“监听URL变化,渲染对应组件”:
- HashRouter:基于 URL 中的 # (哈希值),哈希变化不会触发页面刷新;通过监听 window.onhashchange 事件,感知URL变化后,匹配对应的 Route 组件并渲染。
- BrowserRouter:基于 HTML5 的 History API ( pushState 、 replaceState ),URL 无 # ,更美观;通过 History API 修改URL(不刷新页面),并监听 popstate 事件(处理浏览器前进/后退),匹配路由并渲染组件。