欢迎光临
我们一直在努力

React相关面试题

React 高频面试题(2026版):基础+进阶+手写+项目实战全覆盖

结合最新面试趋势(React 18、Hooks 最佳实践、服务端渲染),整理了分梯度、带答题思路、附手写代码的核心面试题,覆盖入门到资深级考点,帮你精准抓住重点、高效备考。

一、基础必懂(入门级,80%面试会问)

1. React 的核心特性有哪些?

核心答案:

  • 声明式编程:关注“做什么”而非“怎么做”,只需描述UI状态,React 自动处理DOM更新;
  • 组件化:UI拆分为独立可复用的组件,降低耦合、提升维护性;
  • 单向数据流:数据从父组件流向子组件,子组件不直接修改父组件数据,保证数据可追溯;
  • 虚拟DOM(VDOM):用JS对象描述DOM结构,通过diff算法最小化DOM操作;
  • JSX:语法糖(React.createElement的简写),允许在JS中写HTML结构,提升开发效率。

2. JSX 是什么?为什么不能直接运行,需要编译?

核心答案:

  • JSX 是 React 的语法扩展,本质是 React.createElement(component, props, …children) 的语法糖;
  • 示例:<div className="box">Hello</div> 编译后 → React.createElement('div', { className: 'box' }, 'Hello');
  • 不能直接运行的原因:浏览器无法识别JSX语法,需通过Babel编译为普通JS代码后才能执行。

3. React 组件的两种定义方式及区别?

维度函数组件(Function Component)类组件(Class Component)
写法 纯函数,返回JSX 继承React.Component,通过render返回JSX
状态管理 需用Hooks(useState/useReducer) 用this.state/this.setState
生命周期 需用Hooks(useEffect) 内置生命周期方法(componentDidMount等)
性能 更轻量,无实例开销 有实例开销,略重
TS支持 更简洁,类型推断友好 需绑定this,类型配置复杂
适用场景 大部分场景(React16.8+推荐) 老项目/需复杂生命周期场景

4. 简述 React 的单向数据流及优势

核心答案:

  • 单向数据流:数据只能从父组件通过props传递给子组件,子组件若要修改数据,需调用父组件传递的回调函数,由父组件更新数据后再回传;
  • 优势:
  • 数据流向清晰,便于调试(可快速定位数据修改位置);
  • 避免子组件随意修改数据导致的状态混乱;
  • 组件解耦,父组件控制数据,子组件仅负责展示/交互。

5. props 和 state 的区别?

维度propsstate
来源 父组件传递 组件内部定义
可变性 只读(子组件不能修改) 可变(通过setState/useState更新)
触发更新 父组件修改props,子组件重新渲染 组件内部更新state,自身重新渲染
用途 组件间通信 组件内部状态管理

二、Hooks 核心(中级,高频区分度考点)

1. React Hooks 出现的背景?解决了什么问题?

核心答案:

  • 背景:类组件存在的痛点——
  • 逻辑复用困难(HOC/Render Props 导致嵌套地狱);
  • 复杂组件逻辑分散(生命周期方法中混杂不同逻辑,如componentDidMount同时请求数据+初始化定时器);
  • this指向问题(类组件方法需绑定this,易出错);
  • 解决的问题:
  • 用Hooks将分散的逻辑聚合,按功能组织代码;
  • 函数组件支持状态管理和生命周期逻辑;
  • 逻辑复用更简洁(自定义Hooks),无嵌套地狱;
  • 无需处理this指向问题。

2. 常用 Hooks 及使用场景(useState/useEffect/useRef/useMemo/useCallback)

Hook核心作用典型使用场景
useState 函数组件声明状态 管理组件内部简单状态(如输入框值、弹窗显隐)
useEffect 处理副作用(数据请求/定时器/事件绑定) 组件挂载请求数据、卸载清理定时器/事件监听
useRef 保存可变值(不触发渲染) 获取DOM元素、保存定时器ID、缓存上一次状态
useMemo 缓存计算结果(避免重复计算) 复杂数据推导(如列表过滤排序)、减少不必要渲染
useCallback 缓存函数引用(避免函数重新创建) 传递给子组件的回调函数(配合React.memo优化)

关键示例:

// useEffect 副作用处理(挂载请求数据,卸载清理定时器)
useEffect(() => {
// 挂载时请求数据
const fetchData = async () => {
const res = await api.getUserList()
setList(res.data)
}
fetchData()

// 挂载时启动定时器
const timer = setInterval(() => {
setCount(prev => prev + 1)
}, 1000)

// 卸载时清理副作用
return () => {
clearInterval(timer)
}
}, []) // 空依赖:仅挂载/卸载执行

// useMemo 缓存计算结果
const filteredList = useMemo(() => {
return list.filter(item => item.age > 18)
}, [list]) // 仅list变化时重新计算

// useCallback 缓存函数
const handleClick = useCallback(() => {
setCount(prev => prev + 1)
}, []) // 依赖为空,函数引用不变

3. useEffect 的依赖项及执行规则?常见坑?

核心执行规则:

  • 依赖项为空数组 []:仅在组件挂载时执行一次,卸载时执行返回的清理函数;
  • 依赖项为特定值 [a, b]:组件挂载时执行,且a/b变化时重新执行,同时先执行上一次的清理函数;
  • 无依赖项:组件每次渲染后都执行;

常见坑:

  • 遗漏依赖项:如useEffect中使用了state/props但未加入依赖,导致逻辑不生效;
  • 无限循环:在useEffect中更新state,且state加入依赖,未做条件判断;
  • 清理副作用不及时:如未清理定时器/事件监听,导致内存泄漏。
  • 4. 自定义 Hooks 的定义及使用场景?

    核心答案:

    • 定义:以use开头的自定义函数,封装可复用的逻辑,内部可调用内置Hooks;
    • 核心规则:只能在函数组件/自定义Hooks中调用,不能在普通函数/条件语句中调用;
    • 典型场景:请求数据、表单校验、防抖节流、监听窗口大小等。

    自定义Hook示例(useRequest.js):

    // 封装通用请求逻辑
    import { useState, useEffect } from 'react'

    export function useRequest(api, params = []) {
    const [data, setData] = useState(null)
    const [loading, setLoading] = useState(true)
    const [error, setError] = useState(null)

    const fetchData = async () => {
    try {
    setLoading(true)
    const res = await api(…params)
    setData(res.data)
    } catch (e) {
    setError(e)
    } finally {
    setLoading(false)
    }
    }

    useEffect(() => {
    fetchData()
    }, params) // 参数变化重新请求

    return { data, loading, error, refetch: fetchData }
    }

    // 组件中使用
    import { useRequest } from '@/hooks/useRequest'
    const { data, loading, refetch } = useRequest(api.getUserList, [1, 10])

    5. React.memo、useMemo、useCallback 的区别及使用场景?

    优化手段核心作用适用场景
    React.memo 缓存组件,仅props变化时重新渲染 纯展示型子组件,props不频繁变化
    useMemo 缓存计算结果,避免重复计算 复杂计算(如列表过滤排序)
    useCallback 缓存函数引用,避免函数重新创建 传递给子组件的回调函数(配合React.memo)

    优化示例:

    // 子组件:用React.memo缓存
    const Child = React.memo(({ onClick, data }) => {
    return <button onClick={onClick}>{data}</button>
    })

    // 父组件:用useCallback缓存函数,useMemo缓存数据
    const Parent = () => {
    const [count, setCount] = useState(0)
    // 缓存函数,避免每次渲染重新创建
    const handleClick = useCallback(() => {
    console.log('click')
    }, [])
    // 缓存数据,避免每次渲染重新计算
    const data = useMemo(() => `count: ${count}`, [count])

    return <Child onClick={handleClick} data={data} />
    }

    三、进阶核心(资深级,原理+实战考点)

    1. React 虚拟DOM及diff算法原理?

    虚拟DOM:用JS对象描述DOM节点的结构和属性(如 { type: 'div', props: { className: 'box' }, children: [] }),避免直接操作真实DOM(DOM操作比JS运算慢100+倍)。

    diff算法核心规则(React 18):

  • 同层比较:只对比同一层级的节点,不跨层级比较(如根节点div不会和子节点p比较);
  • 类型优先:节点类型不同(如div vs p),直接销毁旧节点、创建新节点;类型相同则对比props;
  • 列表对比:
    • 依赖key唯一标识节点,避免就地复用导致数据错乱;
    • 采用“最长递增子序列”算法,最小化列表节点的移动次数;
  • React 18优化:支持并发渲染,diff过程可中断,优先处理高优先级任务(如用户输入)。
  • 关键考点:列表渲染为什么必须加key?

    • 不加key:React会“就地复用”节点(列表排序/过滤后,仅更新内容不移动DOM),导致表单值错乱、动画异常;
    • 禁止用index做key:列表顺序变化时index也会变,失去唯一标识作用,推荐用后端返回的唯一ID。

    2. React 18 的核心新特性?

    核心答案:

    • 并发渲染(Concurrent Rendering):渲染过程可中断、恢复,优先处理高优先级任务(如用户输入、动画),提升交互流畅度;
    • 自动批处理(Automatic Batching):将多个state更新合并为一次渲染,减少渲染次数(如Promise/定时器中的setState也会批处理);
    • useTransition:标记低优先级更新(如列表筛选),避免阻塞高优先级操作(如输入框输入);
    • Suspense:支持数据请求 Suspense(配合React Query/SWR),实现“加载中”占位,简化异步渲染逻辑;
    • createRoot:替代ReactDOM.render,启用React 18新特性。

    useTransition示例:

    import { useState, useTransition } from 'react'

    const Search = () => {
    const [input, setInput] = useState('')
    const [list, setList] = useState([])
    const [isPending, startTransition] = useTransition()

    const handleInput = (e) => {
    // 高优先级:立即更新输入框
    setInput(e.target.value)
    // 低优先级:标记为过渡更新,不阻塞输入
    startTransition(() => {
    // 模拟复杂列表筛选
    const filteredList = bigList.filter(item => item.includes(e.target.value))
    setList(filteredList)
    })
    }

    return (
    <div>
    <input value={input} onChange={handleInput} />
    {isPending && <div>加载中…</div>}
    <ul>{list.map(item => <li key={item}>{item}</li>)}</ul>
    </div>
    )
    }

    3. React 状态管理方案对比(useState/useReducer/Redux/Zustand/Jotai)

    方案核心特点适用场景
    useState 轻量,管理组件内部简单状态 单个组件/小型组件状态
    useReducer 基于Redux思想,管理复杂状态逻辑 组件内部复杂状态(如多状态联动)
    Redux 全局状态,中间件丰富(Thunk/Saga) 大型应用,需严格状态规范
    Zustand 轻量全局状态,无Provider嵌套 中小型应用,追求简洁
    Jotai 原子化状态,细粒度更新 需精准控制渲染的场景

    Zustand示例(轻量全局状态):

    // store.js
    import { create } from 'zustand'

    const useUserStore = create((set) => ({
    name: '张三',
    age: 20,
    updateName: (newName) => set({ name: newName }),
    incrementAge: () => set((state) => ({ age: state.age + 1 }))
    }))

    // 组件中使用
    const User = () => {
    const { name, age, updateName } = useUserStore()
    return (
    <div>
    <p>{name}({age}岁)</p>
    <button onClick={() => updateName('李四')}>修改姓名</button>
    </div>
    )
    }

    4. React 性能优化的核心手段?

    (1)渲染优化
    • 避免不必要的渲染:
      • 用React.memo缓存纯组件;
      • 用useCallback缓存传递给子组件的函数;
      • 用useMemo缓存复杂计算结果;
    • 拆分组件:将大组件拆分为小型纯组件,减少渲染范围;
    • 懒加载组件:React.lazy + Suspense 按需加载组件。
    (2)数据优化
    • 列表虚拟滚动:用react-window/react-virtualized渲染长列表,只渲染可视区域;
    • 防抖节流:搜索框输入防抖、滚动/resize事件节流;
    • 缓存请求数据:用SWR/React Query缓存接口数据,避免重复请求。
    (3)打包优化
    • 代码分割:React.lazy 拆分代码包,减少首屏加载体积;
    • Tree Shaking:移除未使用的代码(需ES模块);
    • CDN引入第三方库:如React、ReactDOM通过CDN引入,减少打包体积。
    (4)运行时优化
    • 减少DOM操作:用React状态驱动视图,避免手动操作DOM;
    • 清理副作用:useEffect中及时清理定时器/事件监听,避免内存泄漏;
    • 避免在渲染中创建函数/对象:如<Child onClick={() => {}} /> 会导致子组件每次重新渲染。

    5. React 项目如何处理跨域?

    和Vue跨域方案一致,核心分两类:

    (1)开发环境(本地调试)
    • 配置代理(Create React App示例):// src/setupProxy.js
      const { createProxyMiddleware } = require('http-proxy-middleware')
      module.exports = function(app) {
      app.use(
      '/api',
      createProxyMiddleware({
      target: 'http://localhost:3000', // 后端接口地址
      changeOrigin: true,
      pathRewrite: { '^/api': '' } // 去掉/api前缀
      })
      )
      }

    (2)生产环境
    • 后端配置CORS:设置Access-Control-Allow-Origin为前端域名;
    • Nginx反向代理:将前端请求转发到后端,避免跨域。

    四、手写题(高频压轴)

    1. 实现自定义 Hook useDebounce(防抖)

    import { useState, useEffect } from 'react'

    // 防抖Hook:延迟执行函数,避免频繁触发
    export function useDebounce(value, delay = 300) {
    const [debouncedValue, setDebouncedValue] = useState(value)

    useEffect(() => {
    // 设置定时器,延迟更新
    const timer = setTimeout(() => {
    setDebouncedValue(value)
    }, delay)

    // 每次value变化时,清除上一次的定时器
    return () => clearTimeout(timer)
    }, [value, delay])

    return debouncedValue
    }

    // 组件中使用
    const Search = () => {
    const [input, setInput] = useState('')
    // 防抖后的输入值
    const debouncedInput = useDebounce(input, 500)

    // 防抖后请求接口
    useEffect(() => {
    if (debouncedInput) {
    api.search(debouncedInput).then(res => {
    setList(res.data)
    })
    }
    }, [debouncedInput])

    return <input value={input} onChange={(e) => setInput(e.target.value)} />
    }

    2. 实现简易版 useState Hook

    // 模拟React的useState实现(简化版)
    let state = [] // 存储状态
    let index = 0 // 标记当前Hook的索引

    function useState(initialValue) {
    const currentIndex = index // 保存当前索引
    // 初始化状态
    state[currentIndex] = state[currentIndex] || initialValue

    // 更新状态函数
    const setState = (newValue) => {
    // 支持函数式更新
    if (typeof newValue === 'function') {
    state[currentIndex] = newValue(state[currentIndex])
    } else {
    state[currentIndex] = newValue
    }
    // 模拟重新渲染(实际React会触发组件重渲染)
    render()
    }

    index++ // 索引递增,保证多个useState顺序一致
    return [state[currentIndex], setState]
    }

    // 模拟渲染函数
    function render() {
    index = 0 // 每次渲染重置索引
    // 实际React会重新执行组件函数
    console.log('组件重新渲染,当前state:', state)
    }

    // 测试
    const [count, setCount] = useState(0)
    setCount(1) // 输出:组件重新渲染,当前state: [1]
    setCount(prev => prev + 1) // 输出:组件重新渲染,当前state: [2]

    总结

    核心考点回顾

  • 基础层:React核心特性、JSX原理、props/state区别、组件定义方式;
  • Hooks层:useState/useEffect规则、自定义Hooks、性能优化(React.memo/useMemo/useCallback);
  • 进阶层:虚拟DOM/diff算法、React 18新特性、状态管理方案、性能优化;
  • 实战层:跨域处理、组件懒加载、自定义Hook封装、手写核心逻辑。
  • 答题技巧

    • 基础题:先答核心定义,再补示例/使用场景;
    • Hooks题:结合“副作用”“缓存”“复用”三个关键词展开;
    • 原理题:用“通俗语言+简化代码”解释(如虚拟DOM=“JS对象描述DOM”);
    • 项目题:围绕“性能、复用、可维护”展开,体现实战经验。
    赞(0)
    未经允许不得转载:171主机测评 » React相关面试题
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址