当前位置: 首页 > news >正文

React 面试题总结

目录

相关网址

Redux

准备工作

文件规范

model.js

.jsx 引入 model.js 相关

一、核心概念

1. React 的核心思想是什么?

2. JSX 的本质是什么?

3. Virtual DOM 和 Diff 算法

4. React 事件系统的特点?

5. 受控组件 vs 非受控组件?

二、Hooks

6. useState 的工作原理?

7. useEffect 的使用规则?

8. useEffect vs useLayoutEffect?

9. useMemo 和 useCallback 的区别?

10. useRef 的用途?

11. useContext 的使用与注意事项?

12. 自定义 Hook 的规则?

三、组件设计

13. 类组件 vs 函数组件?

14. React.memo / PureComponent 的作用?

15. 高阶组件(HOC)的概念与问题?

16. children 和组合模式

四、状态管理

17. React 状态管理方案对比

18. useReducer 的使用场景?

19. Redux 核心三原则?

五、性能优化

20. React 有哪些常见的性能优化手段?

21. React 18 的并发特性?

22. key 的作用?为什么不能用 index?

六、路由

23. React Router v6 的主要变化?

七、其他高频题

24. React 的 Fiber 架构是什么?

25. React 的错误边界(Error Boundary)?

26. React Server Components(RSC)是什么?

27. React 中如何处理表单?

28. useImperativeHandle 的作用?

29. StrictMode 的作用?

30. React 19 的主要新特性?


相关网址

react : 快速入门 – React 中文文档

Ant Design : 介绍 - Ant Design

Redux

redux 是 react 开发时,一种状态管理工具,再开发时,可以将一些方法和数据包括请求之类的封装,再整个项目都可以调用

准备工作

对应依赖

dependencies:{ "umi": "^3.5.0", "umi-request": "^1.4.0", "umi-serve": "^1.9.10", "@umijs/route-utils": "^2.0.0", "dva-model-extend": "^0.1.2", "ahooks": "^3.7.2", "react": "^17.0.0", "react-dev-inspector": "^1.7.0", "react-dom": "^17.0.0", "react-fittext": "^1.0.0", "react-helmet-async": "^1.2.0", "react-router": "^4.3.1", } devDependencies:{ "@umijs/fabric": "^2.8.0", "@umijs/plugin-blocks": "^2.2.0", "@umijs/plugin-esbuild": "^1.4.0", "@umijs/plugin-openapi": "^1.3.0", "@umijs/preset-ant-design-pro": "^1.3.0", "@umijs/preset-dumi": "^1.1.0", "@umijs/preset-react": "^2.1.0", "umi-serve": "^1.9.10" }

@/utils/model.js

import dvaModelExtend from 'dva-model-extend' export const createResetStoreModel = (namespace, initState, path) => { let isClear = true return { namespace, reducers: { resetStore(state, { payload = {} }) { return { ...JSON.parse(JSON.stringify(initState)), ...payload, } }, }, subscriptions: { setup({ dispatch, history }) { history.listen(() => { if (history.location.pathname !== path) { isClear = false } if (isClear) { return } if (!isClear) { dispatch({ type: 'resetStore' }) isClear = true } }) }, }, } } export const createRouteLevelModel = (namespace, initState, path, model) => { const resetModel = createResetStoreModel(namespace, initState, path) return dvaModelExtend(model, resetModel, { namespace, reducers: { changeStore(state, { payload }) { return { ...state, ...payload, } }, changeStoreDeeply(state, { payload }) { return Object.assign({}, state, payload) }, }, }) }

文件规范

const.js数据存放 例如:字段富化对象,表格对应数据等

index.jsx首页 默认进入的页面

model.jsredux 相关,公共字段,接口请求和处理等

components子组件,用于放置 index.jsx 中各个组件

model.js

必须有四个变量

namespace当前路由对应的 name type = String

const namespace = 'home'

resetPath当前路由对应的 path type = String

const resetPath = '/app/home'

initState公共数据存储 type = Object

const initState = { dataAll :[] }

model处理模块 type = Object

const model = { namespace, state: JSON.parse(JSON.stringify(initState)), effects: { *fetchList({ payload = {} }, { call, put, select }) { try { // put 调用 model 方法 yield put({ // 对应方法 默认有个 changeStore 用于更新 initState 数据 type: 'changeStoreDeeply', payload: { ...payload, isLoading: true, }, }) // select 用于获取 initState 数据 写法如下 const { searchForm } = yield select((_) => _[namespace]) const body = { ...formatParams(searchForm), ...pageParams } // call 调用对应接口请求 const { data, code, msg } = yield call(getAuthorizationList, body) if (code === 200) { yield put({ type: 'changeStore', payload: { dataAll: data.data || [], }, }) } else { throw new Error(msg) } } catch (e) { const errorMsg = e.message || e message.error(`获取审核信息列表失败${errorMsg ? `:${errorMsg}` : ''}`) } }, }, reducers: { // 可以再这对数据进一步梳理 }, }

将 redux 返出

import { createRouteLevelModel } from '@/utils/model' * * * export default createRouteLevelModel(namespace, initState, resetPath, model)

.jsx 引入model.js 相关

import { connect } from 'umi' function Main({ inclusionConfig, dispatch }) { const { isLoading, isEditable, configList = [], resetConfigList = [], } = inclusionConfig // dispatch({ // type: 'inclusionConfig/changeStore', // payload: { // isEditable: true, // }, // }) return <div>home</div> } // inclusionConfig 就是引入的对应的 redux 可以引入多个 // Main 当前页面的组件 export default connect(({ inclusionConfig,XXX }) => ({ inclusionConfig,XXX }))(Main)

一、核心概念

1. React 的核心思想是什么?

  • 声明式 UI:描述"是什么"而非"怎么做",状态驱动视图

  • 组件化:UI 拆分为独立、可复用的组件

  • 单向数据流:数据自上而下(props),事件自下而上(回调)

  • Virtual DOM:通过 diff 算法最小化真实 DOM 操作

2. JSX 的本质是什么?

JSX 是React.createElement的语法糖,经 Babel 编译后转换为函数调用:

// JSX <div className="box"><span>{text}</span></div> // 编译后 React.createElement('div', { className: 'box' }, React.createElement('span', null, text) )

JSX 不是模板语言,而是 JavaScript 表达式——可以赋值、作为参数传递、在条件/循环中使用。

3. Virtual DOM 和 Diff 算法

Virtual DOM:用 JS 对象描述 DOM 结构,更新时对比新旧虚拟树,计算最小变更再操作真实 DOM。

Diff 策略(O(n)):

  • 同层比较,不跨层级

  • 不同类型的元素 → 销毁重建

  • 同类型元素 → 更新属性

  • 列表通过key识别节点身份

4. React 事件系统的特点?

  • 合成事件(SyntheticEvent):跨浏览器封装,统一接口

  • 事件委托:React 17+ 事件绑定在 root 容器(而非 document)

  • 事件池(React 16):事件对象会被复用,异步访问需e.persist()(React 17+ 已移除事件池)

  • e.stopPropagation()阻止的是 React 合成事件冒泡,不影响原生事件

5. 受控组件 vs 非受控组件?

特性

受控组件

非受控组件

数据源

React state

DOM 自身

获取值

state 变量

ref.current.value

表单验证

实时验证

提交时验证

动态控制

方便

困难

推荐使用受控组件;文件输入等场景用非受控组件。


二、Hooks

6. useState 的工作原理?

const [count, setCount] = useState(0)
  • 每次渲染时,React 按调用顺序维护 hooks 链表

  • setCount触发重新渲染,新渲染中通过顺序获取最新值

  • 更新是异步批处理的(React 18 默认所有场景自动批处理)

  • 函数式更新setCount(prev => prev + 1)可获取最新值

7. useEffect 的使用规则?

useEffect(() => { // 副作用逻辑 return () => { /* 清理函数 */ } }, [dependencies])

依赖数组

执行时机

不传

每次渲染后

[]

仅挂载/卸载

[a, b]

a 或 b 变化时

常见陷阱:

  • 闭包陷值(capture stale value):依赖数组遗漏变量

  • 无限循环:依赖中包含每次渲染都变化的引用

8. useEffect vs useLayoutEffect?

特性

useEffect

useLayoutEffect

执行时机

DOM 绘制后(异步)

DOM 变更后、绘制前(同步)

使用场景

数据请求、订阅、日志

DOM 测量、防闪烁布局

性能影响

不阻塞渲染

阻塞渲染

9. useMemo 和 useCallback 的区别?

const memoizedValue = useMemo(() => expensiveCalc(a, b), [a, b]) const memoizedFn = useCallback(() => doSomething(a), [a])
  • useMemo:缓存计算结果

  • useCallback:缓存函数引用(等价于useMemo(() => fn, deps)

何时使用:

  • 传递给React.memo子组件的回调 →useCallback

  • 昂贵计算 →useMemo

  • 不要过度优化:简单计算不需要 memo

10. useRef 的用途?

  • 获取 DOM 元素引用:<input ref={inputRef} />

  • 存储跨渲染的可变值(不触发重新渲染):定时器 ID、前一次的值

  • 组件实例引用(类组件 / forwardRef)

const renderCount = useRef(0) useEffect(() => { renderCount.current++ }) // 不会触发重渲染

11. useContext 的使用与注意事项?

const ThemeContext = createContext('light') // Provider <ThemeContext.Provider value={theme}> <App /> </ThemeContext.Provider> // Consumer const theme = useContext(ThemeContext)

注意:Context 值变化会导致所有消费者重新渲染,即使它们只用了 context 中的部分字段。优化方式:

  • 拆分 Context

  • useMemo 包裹 value

  • 使用状态管理库(Zustand/Jotai)替代

12. 自定义 Hook 的规则?

  • 命名必须以use开头

  • 只在组件顶层或其他 Hook 中调用(不能在条件/循环中)

  • 每次调用产生独立的状态(不同组件间不共享状态)

function useDebounce(value, delay) { const [debouncedValue, setDebouncedValue] = useState(value) useEffect(() => { const timer = setTimeout(() => setDebouncedValue(value), delay) return () => clearTimeout(timer) }, [value, delay]) return debouncedValue }

三、组件设计

13. 类组件 vs 函数组件?

对比项

类组件

函数组件 + Hooks

语法

class + render

function + return

状态

this.state

useState

生命周期

完整钩子

useEffect 统一处理

this 问题

存在

不存在

逻辑复用

HOC / render props

自定义 Hook

性能

实例化开销

更轻量

趋势

维护旧代码

官方推荐

14. React.memo / PureComponent 的作用?

  • React.memo:高阶组件,对函数组件的 props 做浅比较,相同则跳过渲染

  • PureComponent:类组件版本,对 props + state 做浅比较

const Child = React.memo(({ data, onClick }) => { return <div onClick={onClick}>{data.name}</div> })

注意:如果 props 中包含每次渲染都新建的对象/函数,memo 无效——需配合 useMemo/useCallback。

15. 高阶组件(HOC)的概念与问题?

HOC 是一个接收组件、返回新组件的函数,用于逻辑复用:

function withAuth(WrappedComponent) { return function(props) { const isAuth = useAuth() if (!isAuth) return <Redirect to="/login" /> return <WrappedComponent {...props} /> } }

问题:props 命名冲突、嵌套地狱、静态方法丢失、ref 无法透传(需 forwardRef)。现代项目用自定义 Hook 替代。

16. children 和组合模式

// 插槽式组合(推荐) <Card> <Card.Header>Title</Card.Header> <Card.Body>{content}</Card.Body> </Card> // render props <DataFetcher url="/api/users"> {({ data, loading }) => loading ? <Spin /> : <UserList data={data} />} </DataFetcher>

组合优于继承是 React 的核心设计哲学。


四、状态管理

17. React 状态管理方案对比

方案

特点

适用场景

useState/useReducer

内置,局部状态

组件内部

Context

内置,跨层级传递

主题、用户信息等低频更新

Redux/RTK

单一 store,可预测

大型应用、复杂状态流

Zustand

极简,无 Provider

中小型应用

Jotai

原子化

细粒度状态

React Query/SWR

服务端状态管理

接口缓存、请求去重

18. useReducer 的使用场景?

当状态逻辑复杂(多个子值、依赖前一个状态)或需要传递 dispatch 给深层组件时:

function reducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 } case 'decrement': return { count: state.count - 1 } default: throw new Error() } } const [state, dispatch] = useReducer(reducer, { count: 0 })

19. Redux 核心三原则?

  • 单一数据源:整个应用状态存储在一棵对象树中

  • 状态只读:唯一改变方式是 dispatch action

  • 纯函数修改:reducer 是纯函数(state + action → newState)


五、性能优化

20. React 有哪些常见的性能优化手段?

避免不必要渲染:

  • React.memo + useCallback/useMemo

  • 状态下沉(将状态移到真正需要的组件)

  • 组件拆分(不变的部分抽成独立组件)

减少渲染开销:

  • 虚拟列表(react-window / react-virtuoso)

  • 懒加载(React.lazy + Suspense)

  • 代码分割(动态 import)

批处理与调度:

  • React 18 自动批处理(减少渲染次数)

  • useTransition / useDeferredValue(区分优先级)

  • startTransition 标记非紧急更新

21. React 18 的并发特性?

  • Automatic Batching:所有场景(包括 setTimeout、Promise)自动批处理

  • useTransition:将更新标记为非紧急,可被打断

  • useDeferredValue:延迟更新,类似防抖但由 React 调度

  • Suspense for Data Fetching:配合流式 SSR

const [isPending, startTransition] = useTransition() function handleSearch(e) { // 紧急:更新输入框 setInput(e.target.value) // 非紧急:更新搜索结果 startTransition(() => { setSearchResults(filterData(e.target.value)) }) }

22. key 的作用?为什么不能用 index?

  • key 帮助 React 识别列表元素的身份

  • 用 index 作 key:元素增删时,index 对应关系变化 → 状态错乱、不必要的 DOM 操作

  • 正确做法:使用数据中唯一稳定的标识符(id)


六、路由

23. React Router v6 的主要变化?

  • <Switch><Routes>

  • <Route>component/renderelement={<Component />}

  • 嵌套路由使用相对路径 +<Outlet />

  • useNavigate替代useHistory

  • 新增 loader/action(数据路由模式)

<Routes> <Route path="/" element={<Layout />}> <Route index element={<Home />} /> <Route path="users/:id" element={<UserDetail />} /> <Route path="*" element={<NotFound />} /> </Route> </Routes>

七、其他高频题

24. React 的 Fiber 架构是什么?

Fiber 是 React 16 引入的新协调引擎:

  • 将渲染工作拆分为小的工作单元(Fiber 节点)

  • 支持中断/恢复:浏览器空闲时执行,有高优先级任务时暂停

  • 实现了增量渲染,避免长时间阻塞主线程

  • 为并发模式奠定基础

25. React 的错误边界(Error Boundary)?

用类组件的componentDidCatchstatic getDerivedStateFromError捕获子组件树的渲染错误:

class ErrorBoundary extends React.Component { state = { hasError: false } static getDerivedStateFromError(error) { return { hasError: true } } componentDidCatch(error, info) { logError(error, info.componentStack) } render() { if (this.state.hasError) return <FallbackUI /> return this.props.children } }

注意:不能捕获事件处理、异步代码、服务端渲染、自身的错误。函数组件目前无法直接实现错误边界。

26. React Server Components(RSC)是什么?

  • 在服务端执行的组件,不发送 JS 到客户端

  • 可以直接访问数据库/文件系统

  • 与 Client Components 通过"use client"指令区分

  • 减少客户端 JS bundle 体积

  • Next.js App Router 默认使用 RSC

27. React 中如何处理表单?

// 受控方式 function Form() { const [form, setForm] = useState({ name: '', email: '' }) const handleChange = (e) => { setForm(prev => ({ ...prev, [e.target.name]: e.target.value })) } return ( <form onSubmit={handleSubmit}> <input name="name" value={form.name} onChange={handleChange} /> <input name="email" value={form.email} onChange={handleChange} /> </form> ) }

复杂表单推荐使用 React Hook Form 或 Formik。

28. useImperativeHandle 的作用?

配合forwardRef自定义暴露给父组件的实例方法:

const FancyInput = forwardRef((props, ref) => { const inputRef = useRef() useImperativeHandle(ref, () => ({ focus: () => inputRef.current.focus(), getValue: () => inputRef.current.value, })) return <input ref={inputRef} /> })

29. StrictMode 的作用?

开发模式下帮助发现潜在问题:

  • 双重调用渲染/Effect(检测副作用是否纯净)

  • 警告使用废弃 API

  • 检测意外的副作用

仅在开发环境生效,不影响生产构建。

30. React 19 的主要新特性?

  • Actions:表单处理新范式(useActionState、useFormStatus)

  • use():在组件/Hook 中读取 Promise 和 Context 的新 API

  • React Compiler:自动 memoization,减少手动 useMemo/useCallback

  • ref 作为 prop:函数组件可直接接收 ref,无需 forwardRef

  • Document Metadata:组件中直接渲染<title><meta>

http://www.zskr.cn/news/1449460.html

相关文章:

  • 2026 年 6 月教资在线刷题实测:免费高效工具全对比 - 讲清楚了
  • 如何彻底掌控你的惠普OMEN游戏本性能?OmenSuperHub终极指南
  • OpenAI 的「无 App」手机:动态 UI 生成的技术原理与未来交互
  • 获取联通光猫的管理员密码
  • Hermes WebUI环境变量审批状态:ADR-007实现机制
  • 晨芯阳HC9629高输入电压线性稳压器
  • AI第四周的学习计划 Linux+SQL 基础
  • 如何通过微信投票组织投票活动?小程序搭建指南 - 投票小程序
  • HRNetPose部署常见问题与解决方案:从模型加载到推理优化
  • 终极指南:如何用openpilot开源系统将300+款汽车升级为智能驾驶座驾
  • 深入理解LUKE架构:luke-japanese-base-finetuned-ner-openmind背后的核心技术
  • 2026论文全流程终极榜单:10款降AI率网站,查重降重+降AIGC一次通关 - 降AI小能手
  • 2026 年服装拿货哪里最便宜权威排行榜:8 大渠道深度测评(真实店主回访 + 全维度解析) - 资讯纵览
  • 自动驾驶感知---纯视觉SOTA的Occupancy
  • 为什么选择4-bit量化?PersonaPlex-7B-MLX模型压缩技术深度解析
  • 开源模块化履带机器人平台UNITRAC:从设计到制作全解析
  • 终极指南:5分钟搭建基于多智能体LLM交易系统的完整教程
  • 高效开源工具深度解析:Czkawka三款跨平台重复文件清理工具实战指南
  • Kronos金融预测模型:揭秘AI如何理解K线语言的技术革命
  • PP-OCRv5_mobile_rec_safetensors全面解析:新一代多语言文本识别模型如何突破四大语言识别难题
  • 如何永久保存微信聊天记录:WeChatMsg的完整本地化数据备份方案
  • Ultimate Vocal Remover GUI:基于深度神经网络的音频分离技术解析与实践指南
  • AgentRAG:企业AI从“查资料”到“会思考”的内核升级
  • Boss Show Time终极指南:如何免费快速提升求职效率的完整教程
  • MD-Judge-v0.1技术内幕:32层隐藏网络如何实现精准安全评估
  • 解锁AMD Ryzen处理器隐藏性能:SMUDebugTool完全指南
  • C++初阶(11)/STL(四):stack和queue
  • 电路设计入门:从欧姆定律到PCB制作,手把手带你点亮创意
  • 鸣潮模组终极指南:5分钟解锁15+隐藏功能,全面升级游戏体验
  • 别再只盯着GPT-4V了!用Qwen-VL-Chat本地部署,5分钟搭建你的多图对话AI助手