React 前端 50 个基础高频面试题
React 前端面试常见 50 题涵盖组件原理、Hooks、状态管理、路由及性能优化。内容涉及虚拟 DOM、JSX、生命周期、父子通信、Redux 对比等核心知识点。解答了 setState 异步机制、useEffect 执行顺序、Diff 算法差异及 React 18 新特性。适合求职者复习基础与进阶概念。

React 前端面试常见 50 题涵盖组件原理、Hooks、状态管理、路由及性能优化。内容涉及虚拟 DOM、JSX、生命周期、父子通信、Redux 对比等核心知识点。解答了 setState 异步机制、useEffect 执行顺序、Diff 算法差异及 React 18 新特性。适合求职者复习基础与进阶概念。

前端基础高频面试题之-- React 篇
本文汇总了前端面试中经常问到的 React 基础高频面试题,面试常问的基本都在这里。
用于构建用户界面的 JavaScript 库,提供了 UI 层面的解决方案,遵循组件设计模式、声明式编程范式和函数式编程概念,以使前端应用程序更高效,使用虚拟 DOM 来有效地操作 DOM,遵循从高阶组件到低阶组件的单向数据流,帮助我们将界面成了各个独立的小块,每一个块就是组件,这些组件之间可以组合、嵌套,构成整体页面。
JSX 是 JavaScript XML 的简写。是 React 使用的一种文件,它利用 JavaScript 的表现力和类似 HTML 的模板语法。这使得 HTML 文件非常容易理解。此文件能使应用非常可靠,并能够提高其性能(说白了就是可以在 js 中写 html)。
浏览器只能处理 JavaScript 对象,而不能读取常规 JavaScript 对象中的 JSX。所以为了使浏览器能够读取 JSX,首先,需要用像 Babel 这样的 JSX 转换器将 JSX 文件转换为 JavaScript 对象,然后再将其传给浏览器。
组件是 React 应用的构建块。它们是独立且可重用的代码片段,用于定义 UI 的一部分。组件可以是类组件或函数组件,并且可以维护自己的状态和生命周期。
每个 React 组件强制要求必须有一个 render()。它返回一个 React 元素,是原生 DOM 组件的表示。如果需要渲染多个 HTML 元素,则必须将它们组合在一个封闭标记内,例如 <form>、<group>、<div> 等。此函数必须保持纯净,即必须每次调用时都返回相同的结果。
Props 是 React 中属性的简写。它们是只读组件,必须保持纯,即不可变。它们总是在整个应用中从父组件传递到子组件。子组件永远不能将 prop 送回父组件。这有助于维护单向数据流,通常用于呈现动态生成的数据。
状态是 React 组件的核心,是数据的来源,必须尽可能简单。基本上状态是确定组件呈现和行为的对象。与 props 不同,它们是可变的,并创建动态和交互式组件。可以通过 this.state() 访问它们。
箭头函数(=>)是用于编写函数表达式的简短语法。这些函数允许正确绑定组件的上下文,因为在 ES6 中默认下不能使用自动绑定。使用高阶函数时,箭头函数非常有用。
好处:
高阶组件是重用组件逻辑的高级方法,是一种源于 React 的组件模式。HOC 是自定义组件,在它之内包含另一个组件。它们可以接受子组件提供的任何动态,但不会修改或复制其输入组件中的任何行为。你可以认为 HOC 是'纯(Pure)'组件。
纯(Pure)组件是可以编写的最简单、最快的组件。它们可以替换任何只有 render() 的组件。这些组件增强了代码的简单性和应用的性能。
key 用于识别唯一的 Virtual DOM 元素及其驱动 UI 的相应数据。它们通过回收 DOM 中当前所有的元素来帮助 React 优化渲染。这些 key 必须是唯一的数字或字符串,列表元素需要一个唯一的 key 来帮助 React 识别哪些项已经改变、添加或删除。这提高了渲染列表的性能,尤其是在进行列表项的重新排序或操作时。
React 路由是一个构建在 React 之上的强大的路由库,它有助于向应用程序添加新的屏幕和流。这使 URL 与网页上显示的数据保持同步。它负责维护标准化的结构和行为,并用于开发单页 Web 应用。React 路由有一个简单的 API。
因为解构赋值的原因:
React 16.6 之后,React 提供了 React.lazy 方法来支持组件的懒加载。配合 webpack 的 code-splitting 特性,可以实现按需加载。
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
0、设计理念
React: 更倾向于函数式编程思想,推崇组件的不可变性和单向数据流。Vue: 结合了响应式编程和模板系统,致力于简化开发过程。
1、组件化方式不同 React 组件包含状态和行为,所有组件共享一个状态树 Vue 每个组件都有自己的状态和行为,并且可以很容易将数据和行为绑定在一起
2、数据驱动方式不同 React 主要采用单向数据流,组件状态通过 setState 方法更新 Vue 支持双向数据绑定(使用 v-model 指令),适合于简化表单输入等场景。
3、模板语法不同 React 使用 JSX(JavaScript XML),将标记语言与 JavaScript 逻辑混写。Vue 使用基于 HTML 的模板语法,允许开发者使用纯 HTML、CSS 和 JavaScript,支持指令
4、生命周期不同 React 生命周期:初始化、更新、卸载 Vue 生命周期:创建、挂载、更新、销毁
5、状态管理方式不同 React 状态管理通常通过使用 Context API 或引入如 Redux、MobX 的库来实现。Vue 提供了 Vuex 作为官方的状态管理解决方案。
6、性能优化方式不同 React 性能优化:React.memo、shouldComponentUpdate Vue 性能优化:keep-alive、v-if
7、响应式系统 React: 通过 setState 和 useState 等 API 显式地触发 UI 更新。Vue: 通过其响应式系统自动追踪依赖并在数据变化时更新视图。
8、类型支持 React: 原生支持 JavaScript,但可以很好地与 TypeScript 结合。Vue: Vue 3 提供了更好的 TypeScript 支持。
父组件 => 子组件:
子组件 => 父组件:
兄弟组件之间:
不相关的组件之间:
useReducer 是 React Hooks 中的一个函数,用于管理和更新组件的状态。它可以被视为 useState 的一种替代方案,适用于处理更复杂的状态逻辑。相比于 useState,useReducer 在处理复杂状态逻辑时更有优势,因为它允许我们将状态更新的逻辑封装在 reducer 函数中,并根据不同的动作类型执行相应的逻辑。这样可以使代码更具可读性和可维护性,并且更容易进行状态追踪和调试。
1、语法不同、设计思想不同
函数式组件是函数式编程思想,而类组件是面向对象编程思想。面向对象编程将属性和方法封装起来,屏蔽很多细节,不利于测试。
2、生命周期、状态变量
3、复用性
React 18 之前
setState 的'异步'并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的'异步',当然可以通过第二个参数 setState(partialState, callback) 中的 callback 拿到更新后的结果。
React 18 之后 setState 都会表现为异步(即批处理)。
1、Node Server 接收客户端请求,得到当前的请求 url 路径,然后在已有的路由表内查找到对应的组件,拿到需要请求的数据,将数据作为 props、context 或者 store 形式传入组件
2、然后基于 React 内置的服务端渲染方法 renderToString() 把组件渲染为 html 字符串在把最终的 html 进行输出前需要将数据注入到浏览器端
3、浏览器开始进行渲染和节点对比,然后执行完成组件内事件绑定和一些交互,浏览器重用了服务端输出的 html 节点,整个流程结束
useEffect 在 React 的渲染过程中是被异步调用的,用于绝大多数场景;useLayoutEffect 会在所有的 DOM 变更之后同步调用,主要用于处理 DOM 操作、调整样式、避免页面闪烁等问题。也正因为是同步处理,所以需要避免在 useLayoutEffect 做计算量较大的耗时任务从而造成阻塞。
useEffect 是按照顺序执行代码的,改变屏幕像素之后执行(先渲染,后改变 DOM),当改变屏幕内容时可能会产生闪烁;useLayoutEffect 是改变屏幕像素之前就执行了(会推迟页面显示的事件,先改变 DOM 后渲染),不会产生闪烁。useLayoutEffect 总是比 useEffect 先执行。
相同点:
区别:
虚拟 DOM 是内存中的 DOM 表示。React 使用虚拟 DOM 来优化 DOM 的更新过程。它通过比较新旧虚拟 DOM 的差异,并仅更新实际 DOM 中改变的部分,提高应用性能。
Hooks 通常支持提取和重用跨多个组件通用的有状态逻辑,而无需承担高阶组件或渲染 props 的负担。
Hooks 可以轻松地操作函数组件的状态,而不需要将它们转换为类组件。
避免使用生命周期方法。
先执行子组件再执行父组件。React 保证了每次运行 useEffect 的同时,DOM 都已经更新完毕。有一些场景,需要父组件的执行顺序在子组件前面,可以考虑一下使用 useLayoutEffect
受控组件 是 React 控制的组件,input 等表单输入框值不存在于 DOM 中,而是以我们的组件状态存在。每当我们想要更新值时,我们就像以前一样调用 setState。
不受控制组件 是您的表单数据由 DOM 处理,而不是 React 组件,Refs 用于获取其当前值;
Redux 是 React 的第三方状态管理库,创建于上下文 API 存在之前。它基于一个称为存储的状态容器的概念,组件可以从该容器中作为 props 接收数据。更新存储区的唯一方法是向存储区发送一个操作,该操作被传递到一个 reducer 中。reducer 接收操作和当前状态,并返回一个新状态,触发订阅的组件重新渲染。
React 实现类似 Vue keep-alive 的缓存效果,通常需要将组件包裹在 Provider 中,且每个组件需拥有唯一 key。
React 有三种构建组件的方式
虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。
useCallback 和 useMemo 可以用来缓存函数和变量,提高性能,减少资源浪费。但并不是所有的函数和变量都需要用这两者来实现,他也有对应的使用场景。
我们知道 useCallback 可以缓存函数体,在依赖项没有变化时,前后两次渲染时,使用的函数体是一样的。它的使用场景是:
函数作为其他 hook 的依赖项时(如在 useEffect() 中);函数作为 React.memo()(或 shouldComponentUpdate)中的组件的 props;主要是为了避免重新生成的函数,会导致其他 hook 或组件的不必要刷新。
useMemo 用来缓存函数执行的结果。如每次渲染时都要执行一段很复杂的运算,或者一个变量需要依赖另一个变量的运算结果,就都可以使用 useMemo()。
因为在 JavaScript 里 class 是一个关键字,用来定义类。所以在 JSX 里不能再用 class 来表示 HTML 元素的类名了,就用 className 来代替,这样就不会和 JavaScript 的关键字冲突了。
React Diff React 的 Diff 算法主要是基于两个假设:不同类型的元素会产生不同的树;开发人员可以通过设置 key 属性来告知 React 哪些元素在不同的渲染之间是稳定的。在对比时,React 会对新旧虚拟 DOM 树进行深度优先遍历,分层比较节点,当发现节点类型不同时,直接替换整个子树,当节点类型相同且有 key 时,会进行更细致的比较和更新。
Vue Diff Vue 的 Diff 算法在比较节点时,同样会优先判断节点类型是否相同。在处理列表时也依赖 key 属性。不过 Vue 的 Diff 算法在某些细节上与 React 有所不同,例如在静态节点和动态节点的处理上,Vue 会对静态节点进行优化,尽量减少对静态节点的重复比较。
React 的合成事件,屏蔽了浏览器自带的事件,解决了浏览器的不兼容,
将事件绑定在 document 上,按照冒泡或者捕获的路径去收集真正的事件处理函数,在此过程中会先处理原生事件,然后当冒泡到 document 对象后 普通事件是绑定在真实 DOM 上
在 React 类组件 中,ajax 请求通常放在 componentDidMount 生命周期方法中。因为这个时候组件已经挂载到 DOM 上,可以进行数据的获取操作,并且不会引起额外的渲染。
在 React Hooks 中,ajax 请求通常放在 useEffect hooks 中。
React Hooks 在使用时注意事项:
原因:
React 实现路由拦截的基本思路还是利用 Route 的 render 函数,通过判断拦截条件来实现不同的组件的跳转,从而实现拦截
Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀方案。
例如:一个 Portal 的典型用例是当父组件有 overflow:hidden 或 z-index 样式时,需要子组件能够在视觉上'跳出'其容器。例如:对话框、悬浮卡以及提示框

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online