React面试题

虚拟 DOM

虚拟 DOM 是内存中的轻量级 DOM 树,状态变化时 React 先对比新旧虚拟 DOM 树(Diff 算法),只更新真实 DOM 中变化的部分,减少性能开销 。

什么是 JSX

JSX 是 JavaScript 的语法扩展,写法像 HTML,但实际会被编译成 React.createElement 调用,不能直接在浏览器运行,需要编译工具处理 。

类组件和函数组件有什么区别

类组件用 class 定义,有生命周期方法和 this 状态;函数组件用函数定义

useEffect

useEffect 替代了类组件的 componentDidMount、componentDidUpdate 和 componentWillUnmount,依赖数组控制执行时机,空数组只执行一次

合成事件和原生事件

React 事件是合成事件,统一绑定在 document 上,通过事件委托处理,兼容所有浏览器,阻止冒泡要用 stopPropagation 而非 return false。

HOC、Render Props 和 Hooks 怎么选

三者都解决代码复用,HOC 容易 props 冲突,Render Props 有嵌套地狱,Hooks 最简洁

如何优化 React 性能

用 React.memo 包裹组件避免不必要重渲染,用 useMemo 缓存计算结果,用 useCallback 缓存函数,大列表用虚拟滚动

受控组件和非受控组件

受控组件的表单值由 React 状态控制,非受控组件用 ref 直接读 DOM 值

React 18 的并发渲染是什么

并发渲染允许多个更新任务同时进行,优先级高的先渲染,用 createRoot 替代 ReactDOM.render,提升用户体验

Server Components 有什么用

服务端组件在服务器渲染,不发送 JS 到客户端,减少包体积,适合数据获取和静态内容

Redux 和 Context

小项目用 Context 够用,大项目状态复杂用 Redux 或 Zustand

Suspense 和 Lazy 怎么配合

Suspense 包裹 Lazy 加载的组件,加载时显示 fallback 内容,实现代码分割和按需加载

React 的核心特性有哪些

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

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

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

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

核心答案

  • 背景:类组件存在的痛点------

    1. 逻辑复用困难(HOC/Render Props 导致嵌套地狱);
    2. 复杂组件逻辑分散(生命周期方法中混杂不同逻辑,如componentDidMount同时请求数据+初始化定时器);
    3. this指向问题(类组件方法需绑定this,易出错);
  • 解决的问题:

    1. 用Hooks将分散的逻辑聚合,按功能组织代码;
    2. 函数组件支持状态管理和生命周期逻辑;
    3. 逻辑复用更简洁(自定义Hooks),无嵌套地狱;
    4. 无需处理this指向问题。

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

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

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

核心执行规则

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

自定义 Hooks 的定义及使用场景?

核心答案

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

自定义Hook示例(useRequest.js)

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]);

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

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

React 虚拟DOM及diff算法原理?

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

diff算法核心规则(React 18)

  1. 同层比较:只对比同一层级的节点,不跨层级比较(如根节点div不会和子节点p比较);

  2. 类型优先:节点类型不同(如div vs p),直接销毁旧节点、创建新节点;类型相同则对比props;

  3. 列表对比

    • 依赖key唯一标识节点,避免就地复用导致数据错乱;
    • 采用"最长递增子序列"算法,最小化列表节点的移动次数;
  4. React 18优化:支持并发渲染,diff过程可中断,优先处理高优先级任务(如用户输入)。

React 18 的核心新特性?

核心答案

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

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

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

zustand实例代码

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>
  )
}

Lobster AIjsx

实现自定义 Hook useDebounce

js 复制代码
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)} />;
};

React Fiber ** 是什么?

  • Fiber 是 React 的 协调引擎
  • 将渲染任务拆分为 可中断的小单元
  • 支持优先级调度
  • Fiber 的诞生是为了解决 长时间渲染阻塞主线程 的问题。
相关推荐
一棵白菜1 小时前
mac 部署 n8n
前端
学高数就犯困1 小时前
React:常见的性能优化手段
前端·react.js
天天码行空1 小时前
vkeyboardhand:零依赖虚拟键盘指法组件
前端·javascript·vue.js
东方小月1 小时前
从零开发一个 Coding Agent(五):使用 TypeBox 校验工具参数
前端·人工智能·后端
我要两颗404西柚1 小时前
Stage four:VUE项目上线
前端·javascript·vue.js
尤乐娃子2 小时前
进入大厂(厂子大)实习Day8
前端·笔记·实习
醉城夜风~2 小时前
CSS盒模型(Box Model)
前端·css
雪隐2 小时前
个人电脑玩AI-15让5060 Ti给你打工——MiniMax H3 本地部署实录:一个自带录音棚的视频模型,和它的 NVFP4 瘦身奇遇
前端·人工智能·后端
GuWenyue3 小时前
不用第三方SDK!Vue3原生Fetch实现DeepSeek流式输出,90%前端都会踩的分片解析坑一次性解决
前端·人工智能·llm