Skip to content

React 面试高频问题

核心概念

  • 什么是 React?

    • 用于构建用户界面的 JavaScript 库。
    • 核心:组件化、虚拟 DOM、JSX、单向数据流、声明式编程。
  • React 的主要特性?

    • 组件化、虚拟 DOM、JSX、单向数据流、声明式编程。
  • JSX 的作用和好处?

    • JavaScript XML,在 JavaScript 中编写类似 HTML 的结构。
    • 好处:易读、易写、更接近 HTML、可以使用 JavaScript 全部能力。
  • 什么是虚拟 DOM?作用是什么?

    • 对实际 DOM 的轻量级 JavaScript 对象表示。
    • 作用:提高 UI 更新效率,批量更新 DOM,减少 DOM 操作次数。
  • React 的单向数据流是什么?

    • 数据从父组件流向子组件,子组件通过 props 接收,无法直接修改。
    • 子组件通过回调函数与父组件通信。
  • React 组件的类型?

    • 函数组件: 使用函数定义,更简洁,常用 Hook.
    • 类组件: 拥有状态和生命周期方法,常用。
  • Props 和 State 的区别?

    • Props: 父组件传递给子组件的只读输入。
    • State: 组件内部可变的数据,由组件自身管理,改变会触发重新渲染。
    • 区别: Props外部传入,State组件内部;Props只读,State可变。
  • 常用 React Hooks?

    • useStateuseEffectuseContextuseReduceruseCallbackuseMemouseRef
  • useEffect 的作用?与 componentDidMount, componentDidUpdate 的关系?

    • 作用: 处理副作用(数据获取、订阅、手动修改 DOM 等)。
    • 关系: 可以替代 componentDidMount, componentDidUpdate, 和 componentWillUnmount。通过依赖数组控制执行时机。
  • 什么是 Context?作用?

    • 在组件树中传递数据,避免逐层传递 props。
    • 作用:简化组件间通信,共享全局数据 (例如用户身份验证信息、主题设置)。
  • React 中如何处理事件?

    • 小驼峰命名(如 onClick, onChange)。
    • 事件处理函数作为 JSX 属性的值。
    • 事件处理函数接收事件对象 (Event Object) 作为参数。
    • React 默认阻止事件冒泡。
  • React 组件通信的几种方式?

    • Props、Context、状态管理库(Redux, MobX, Zustand 等)、回调函数、事件发布/订阅、useRef (较少)。

组件 & JSX

  • 受控组件和非受控组件?

    • 受控组件: 状态由 React state 控制 (例如,onChange 更新值)。
    • 非受控组件: 状态由 DOM 本身控制 (例如,使用 ref 获取值)。
  • React 中处理表单的两种方式?

    • 受控组件: 使用 onChange 事件处理程序和 state 控制。
    • 非受控组件: 使用 ref 获取表单元素的值。
  • JSX 中 key 属性的作用?

    • 帮助 React 识别哪些元素发生变化、被添加或被移除。
    • keymap 循环中必须唯一。
    • 提高 React 的性能。
  • React 中如何进行条件渲染?

    • if/else 语句。
    • 三元运算符 (? :)。
    • 逻辑与运算符 (&&)。
  • 如何使用 Fragment? 为什么使用 Fragment

    • <React.Fragment><>
    • 包裹多个 JSX 元素,避免添加额外 DOM 节点。
    • 好处:代码更简洁,避免不必要的 DOM 节点。
  • 什么是高阶组件 (HOC)?如何创建?

    • 接收一个组件作为参数,返回一个新的组件的函数。
    • 创建步骤: 接收一个组件,返回一个新组件,在新组件渲染传入的组件并可以传递 props。
    • 用途: 代码复用、逻辑提取、属性增强。

状态管理

  • 为什么要使用状态管理库?

    • 解决复杂应用中组件间状态共享和数据流管理的问题。
    • 集中管理应用状态,提供可预测的状态更新方式,方便调试和追踪。
  • Redux 的核心概念?

    • Store, Action, Reducer, Dispatch, Selector.
  • Redux 的数据流?

    1. 用户触发 action。
    2. Action dispatched。
    3. Reducer 接收 action 和当前状态。
    4. Reducer 返回新的 state。
    5. Store 通知订阅者。
    6. 组件重新渲染。
  • Redux 中如何处理异步操作?

    • 中间件 (例如 redux-thunkredux-saga)。
  • 你了解哪些状态管理库?

    • Redux, MobX, Zustand, Recoil。

性能优化

  • React 中常用的性能优化技术?

    • shouldComponentUpdate (类组件) 或 React.memo (函数组件)。
    • useMemouseCallback
    • 列表优化 (使用唯一的 key)。
    • 代码分割 (Code Splitting) - React.lazySuspense
    • 优化图片、虚拟化、避免在 render() 中进行耗时操作、使用 immutable 数据结构。
  • React.memo 的作用? 和 shouldComponentUpdate 的关系?

    • React.memo: 优化函数组件的性能,默认浅比较 props 的变化。
    • 关系: React.memoshouldComponentUpdate 的函数组件版本。
  • 如何优化列表渲染的性能?

    • 使用唯一的 key
    • 避免在 render() 函数中进行耗时操作。
    • 虚拟化。
    • 使用 React.memo 优化列表项组件。
  • 什么是代码分割?作用?

    • 将代码拆分成多个小的 bundle。
    • 减少初始加载时间,按需加载代码,改善用户体验。
    • 使用 React.lazySuspense 实现。
  • 什么是懒加载?

    • 在需要的时候才加载资源 (如 JavaScript 文件、图片)。
    • React.lazy 和 Suspense、图片懒加载。

其他

React 学习问答 (新手友好版)

问:你用过哪些 UI 库或组件库?感觉怎么样?

答:

UI 库就像是预先做好的乐高积木,让你不用从零开始搭建按钮、表单、弹窗这些界面元素,可以更快、更规范地开发网页。我用过几个常见的:

  1. Material UI (MUI):

    • 它是什么? 它是谷歌 Material Design 设计风格的 React 实现。很多谷歌产品(如 Gmail, Google Drive)就是这种感觉。
    • 我的评价 (对新人来说):
      • 优点: 非常流行,组件非常全,文档也很好,社区庞大意味着你遇到问题更容易找到答案。外观看起来很现代、专业。
      • 缺点: 有时候想深度定制样式可能需要多花点功夫,因为它有自己的一套样式系统。
      • 新手建议: 是个很不错的起点,因为资源多,用的人也多。
  2. Ant Design (AntD):

    • 它是什么? 另一个非常流行的库,由蚂蚁集团开发,特别适合做企业后台管理系统这类应用。它有自己独特的设计风格。
    • 我的评价 (对新人来说):
      • 优点: 组件极其丰富,特别是表格、表单等复杂组件功能强大。设计规范统一,很适合快速搭建信息密集的界面。
      • 缺点: 定制外观可能比 MUI 稍微复杂一点点(可能需要配置主题文件)。设计风格比较“企业化”,不一定适合所有类型的网站。
      • 新手建议: 如果你明确要做后台管理系统,AntD 是个很棒的选择。
  3. Chakra UI:

    • 它是什么? 一个更侧重于开发者体验和灵活性的库。它大量使用 "样式属性" (Style Props) 来让你直接在组件上写样式。
    • 我的评价 (对新人来说):
      • 优点: 定制非常非常方便!你可以像写行内样式一样直接改组件外观,但又比行内样式强大得多。它对无障碍访问(Accessibility)支持得特别好。文档清晰易懂。
      • 缺点: 可能需要你稍微多写一点样式相关的代码(但这正是它的灵活之处)。相对前两者,可能组件种类稍微少一点点(但核心的都有)。
      • 新手建议: 如果你喜欢灵活定制样式,并且想学习现代的 CSS-in-JS 方式,Chakra UI 是一个绝佳的选择,对新手非常友好。

总结: 没有绝对的好坏,看项目需求和个人喜好。新手可以都简单尝试一下它们的 "Get Started" 教程,看看哪个用起来更顺手。


问:你是怎么给 React 项目做测试的?听过哪些测试工具?

答:

给 React 项目写测试,就像是给你的代码请“质检员”,确保它们能按预期工作,减少 Bug。主要分三种类型:

  1. 单元测试 (Unit Testing):
    • 测什么? 测试最小的代码单元,比如一个独立的函数或一个简单的 React 组件。看它在特定输入下是否返回预期的输出,或者渲染出正确的样子。
    • 好比: 单独测试汽车引擎能不能启动。
  2. 集成测试 (Integration Testing):
    • 测什么? 测试多个组件或模块组合在一起时是否能正常协作。比如,一个表单组件和一个提交按钮组件一起工作,点击按钮后数据是否正确提交。
    • 好比: 测试引擎、变速箱、轮子装在一起后,车子能不能往前开。
  3. 端到端测试 (End-to-End / E2E Testing):
    • 测什么? 模拟真实用户的使用场景,从头到尾测试整个应用流程。比如,用户打开网页 -> 登录 -> 浏览商品 -> 添加到购物车 -> 结账。通常会用自动化工具在真实浏览器里跑。
    • 好比: 一个试驾员把整辆车开上路,测试加速、刹车、转向、空调等所有功能。

常见的测试框架/库:

  • Jest:
    • 它是什么? 一个非常流行的 JavaScript 测试框架。它提供了一整套测试需要的东西:运行测试、判断结果是否正确(断言)、模拟函数(Mocking)等。你可以用它来测任何 JS 代码,包括 React。
    • 好比: 测试工厂里的测试跑道、计时器、检查清单等全套设备。
  • React Testing Library (RTL):
    • 它是什么? 一个专门用来测试 React 组件的,通常和 Jest 一起使用。它的核心理念是:像用户一样去测试你的组件。它鼓励你通过用户能看到或交互的元素(比如按钮文字、输入框标签)来查找和操作组件,而不是依赖组件内部的实现细节。
    • 好比: 测试说明书上写的是“找到写着‘启动’的按钮并按下”,而不是“检查引擎内部的 isRunning 状态是不是 true”。这是目前社区非常推荐的方式。
  • Enzyme:
    • 它是什么? 另一个(曾经很流行的)测试 React 组件的库。它允许你更深入地检查组件的内部状态(state)和属性(props),以及进行“浅渲染”(只渲染组件本身,不渲染子组件)。
    • 好比: 允许测试员在测试时直接拆开引擎看零件。现在很多人更倾向于用 RTL,因为它更关注用户行为。

新手建议: 从学习 Jest + React Testing Library 开始,这是目前的主流组合。先尝试给你的小组件写一些简单的单元测试和集成测试。


问:你对 React 的未来发展怎么看?

答:

我觉得 React 依然会是前端领域非常重要的技术,并且它还在不断进化。对新人来说,不用担心它过时,但要保持学习的心态。有几个趋势值得关注:

  1. React Server Components (RSC): 这是个比较大的变化。简单说,就是未来一部分 React 组件可以直接在服务器上运行并渲染,只把结果发送给浏览器。
    • 好处? 可以减少发送到浏览器的代码量,加快页面加载速度,尤其对网络不好或设备性能差的用户更友好。
    • 对新人的影响? 现在还不用立刻深入掌握,但知道有这个方向,未来可能会接触到。像 Next.js 这样的框架已经在积极应用了。
  2. 并发 (Concurrency): React 正在变得更“聪明”,能更流畅地处理多个更新任务,即使在进行复杂的计算或数据加载时,也能保持界面不卡顿。
    • 好处? 用户体验更好。
    • 对新人的影响? 你写的代码可能不需要大改,但 React 底层会帮你处理得更平滑。
  3. 性能和开发者体验持续优化: React 团队一直在努力让 React 运行得更快,同时让开发者写代码更舒服、更高效。

总结: React 在向着更快、更强、用户体验和开发者体验更好的方向发展。作为学习者,打好基础,同时关注社区动态和官方文档,了解这些新变化就好。


问:你写 React 时遇到过什么问题?怎么解决的?

答:

写代码肯定会遇到问题,这很正常!分享几个 React 里新手常见的问题和解决思路:

  1. 问题:修改了 State,但界面没更新?

    • 可能原因: 最常见的是直接修改了 State 中的对象或数组(比如 myArray.push(newItem)myObject.key = value)。React 判断是否需要更新,通常是看 State 的引用有没有变。直接修改,引用没变,React 就“以为”没变化。
    • 解决方法: 永远使用 setState 函数来更新 State,并且要传入一个全新的对象或数组。
      • 对于数组:setMyArray([...myArray, newItem]) (使用扩展运算符创建新数组)
      • 对于对象:setMyObject({...myObject, key: newValue}) (使用扩展运算符创建新对象)
      • 这叫做“状态不可变性 (Immutability)”,是 React 的核心概念之一。
  2. 问题:useEffect 里面好像陷入了无限循环?

    • 可能原因: useEffect 的第二个参数是依赖数组 (dependency array)。如果这个数组没写对,或者干脆没写,useEffect 可能会在每次组件渲染后都执行。如果在 useEffect 内部又修改了某个导致组件重新渲染的 State,就可能无限循环了。
    • 解决方法:
      • 仔细检查 useEffect 的依赖数组。只放入那些当它们的值改变时,你才需要重新执行 Effect 的变量。
      • 如果 Effect 只需要在组件第一次加载时执行一次(比如请求初始数据),传入一个空数组 []
      • 如果忘记了某个依赖,或者加入了不必要的依赖,都可能出问题。React 官方的 linter (代码检查工具) 通常会对此给出警告。
  3. 问题:数据要一层一层传很多层组件,好麻烦 (Prop Drilling)!

    • 可能原因: 应用结构比较深,顶层组件的数据要给很底层的组件用,只能通过中间的每一层组件都把 props 往下传。
    • 解决方法:
      • 组件组合 (Composition): 重新思考组件结构,看能不能把需要数据的组件作为 children 传下去,而不是直接渲染。
      • Context API: React 内置的解决方案,可以让你创建“全局”数据,在任何层级的子组件里都能直接访问,不用一层层传 props。适合中小型应用或传递主题、用户信息等。
      • 状态管理库 (如 Redux, Zustand): 对于大型应用,或者有复杂共享状态的情况,可以使用专门的状态管理库,把状态集中管理。

解决问题的通用方法:

  • 仔细阅读错误信息! 浏览器控制台的报错通常会给出关键线索。
  • 使用 console.log() 或 Debugger: 在代码里打印变量,或者使用浏览器的开发者工具打断点,一步步看代码执行流程和变量值。
  • React DevTools: 浏览器插件,可以查看组件树、props 和 state,非常有帮助。
  • 缩小范围: 尝试注释掉一部分代码,或者创建一个最小的可复现问题的例子,定位问题源头。
  • 搜索: 把错误信息或问题描述放到 Google 或 Stack Overflow 搜索,很可能别人也遇到过。
  • 提问: 如果自己解决不了,向同事、导师或在线社区求助,记得说清楚你遇到的问题、你尝试过的方法和相关的代码。

新手建议: 遇到问题不要慌,这是学习过程的一部分。多用工具,多思考,多尝试。理解 React 的核心概念(如 State、Props、生命周期/Effect、不可变性)能帮你避免很多常见错误。


问:你对 React 的生态系统了解多少?

答:

React 本身只是一个用于构建用户界面的库(只负责视图 View 层)。但要开发一个完整的应用,我们还需要很多其他的工具和库,这些共同构成了 React 的“生态系统”。就像造汽车,光有引擎 (React) 不够,还需要轮子、方向盘、车身等等。

这个生态系统主要包括:

  1. 包管理器 (Package Managers):

    • 干啥的? 用来安装和管理项目依赖的各种库(比如 React 本身、UI 库等)。
    • 例子: npm, yarn, pnpm
    • 好比: 汽车零件仓库的管理员。
  2. 构建工具 (Build Tools):

    • 干啥的? 把你写的 React 代码 (JSX)、CSS、图片等转换、打包、优化成浏览器能直接运行的静态文件(HTML, CSS, JavaScript)。还能提供开发服务器,让你写代码时能实时看到效果。
    • 例子: Vite (现在非常流行,速度快), Create React App (CRA) (官方出品,曾经是标配,现在相对较少用于新项目), Next.js / Remix (这些是 React 框架,自带了构建能力)。
    • 好比: 汽车的总装生产线。
  3. 路由 (Routing):

    • 干啥的? 在单页面应用 (SPA) 中管理不同的“页面”或视图之间的跳转。虽然看起来像切换了页面,但实际上没有重新加载整个网页。
    • 例子: React Router (最常用), TanStack Router, Next.js Router (Next.js 内置)。
    • 好比: 汽车的导航系统 (GPS)。
  4. 状态管理 (State Management):

    • 干啥的? 当应用变得复杂,很多组件需要共享或修改同一份数据(状态)时,用来更方便、更可预测地管理这些状态。
    • 例子: React Context API (React 内置,适合简单场景), Redux (老牌、功能强大,适合大型复杂应用), Zustand (较新,更简洁易用), Jotai, Recoil
    • 好比: 汽车的中央控制系统,管理油量、速度等信息,仪表盘和引擎都能访问。
  5. UI 库 / 组件库 (UI Libraries):

    • 干啥的? (就是第一个问题提到的) 提供预先制作好的界面组件。
    • 例子: Material UI (MUI), Ant Design, Chakra UI, Tailwind CSS (这是一个 CSS 框架,常与 Headless UI 库如 Radix UI 结合使用)。
    • 好比: 预制好的汽车座椅、仪表盘、按钮等零件。
  6. 测试库 (Testing Libraries):

    • 干啥的? (就是第二个问题提到的) 用来写测试代码,保证应用质量。
    • 例子: Jest, React Testing Library (RTL), Cypress / Playwright (用于 E2E 测试)。
    • 好比: 汽车出厂前的质量检测部门。
  7. 数据请求 (Data Fetching):

    • 干啥的? 帮助你更方便地从服务器(API)获取数据,并处理加载状态、错误、缓存等。
    • 例子: fetch (浏览器内置), axios (流行的第三方库), TanStack Query (React Query) (非常强大,强烈推荐,能极大简化数据获取逻辑), SWR
    • 好比: 汽车加油或者从外部获取信息的系统。

新手建议: 生态系统很大,刚开始不需要全部掌握。通常,一个基础的 React 项目会用到:包管理器 (npm/yarn) + 构建工具 (Vite 是个好选择) + React 本身。如果需要多页面,就加上 路由 (React Router)。如果项目变大,状态共享困难了,再考虑引入 状态管理库。如果想省事,就用 UI 库。边学边用,按需引入就好。