前端八股文-react篇

React 基础概念

1. React 的生命周期方法有哪些?

React 类组件的生命周期分为三个阶段:

挂载阶段:

  • constructor():初始化 state 和绑定方法
  • static getDerivedStateFromProps():在 render 前调用
  • render():渲染组件
  • componentDidMount():组件挂载后调用,适合发起网络请求

更新阶段:

  • static getDerivedStateFromProps():props 变化时调用
  • shouldComponentUpdate():决定组件是否重新渲染
  • render():渲染组件
  • getSnapshotBeforeUpdate():在 DOM 更新前捕获信息
  • componentDidUpdate():组件更新后调用

卸载阶段:

  • componentWillUnmount():组件卸载前清理定时器、取消订阅等

2. React 的函数组件和类组件有什么区别?

特性 函数组件 类组件
语法 普通函数 ES6 class 继承 React.Component
状态管理 使用 Hooks (useState) 使用 this.state
生命周期 使用 useEffect 等 Hooks 有完整的生命周期方法
this 关键字 无 需要绑定 this
性能 更轻量 相对较重
代码量 更简洁 相对冗长

3. 什么是虚拟 DOM?React 如何工作?

虚拟 DOM:

  • 是真实 DOM 的轻量级 JavaScript 表示
  • 用 JavaScript 对象描述 DOM 树结构
  • 通过 diff 算法比较新旧虚拟 DOM 的差异

工作流程:

  1. 当状态改变时,重新渲染组件生成新的虚拟 DOM
  2. 比较新旧虚拟 DOM(diff 算法)
  3. 计算出最小变更集
  4. 批量更新真实 DOM

4. React 的 key 有什么作用?

  • 唯一标识:帮助 React 识别哪些元素被改变、添加或删除
  • 优化性能:减少不必要的 DOM 操作
  • 正确使用 :
    • 应该在数组内的元素上设置 key
    • key 应该在兄弟节点间唯一
    • 不推荐使用 index 作为 key(除非列表静态不变)

React Hooks

5. 常用的 React Hooks 有哪些?

  1. useState:管理组件状态

    javascript 复制代码
    const [state, setState] = useState(initialState);
  2. useEffect:处理副作用

    javascript 复制代码
    useEffect(() => {
      // 副作用代码
      return () => { /* 清理函数 */ };
    }, [dependencies]);
  3. useContext:访问 Context

    javascript 复制代码
    const value = useContext(MyContext);
  4. useReducer:复杂状态逻辑

    javascript 复制代码
    const [state, dispatch] = useReducer(reducer, initialState);
  5. useCallback:记忆函数

    javascript 复制代码
    const memoizedCallback = useCallback(() => { doSomething(a, b); }, [a, b]);
  6. useMemo:记忆值

    javascript 复制代码
    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  7. useRef:访问 DOM 或保存可变值

    javascript 复制代码
    const refContainer = useRef(initialValue);

6. useEffect 和 useLayoutEffect 的区别?

特性 useEffect useLayoutEffect
执行时机 在浏览器绘制后异步执行 在 DOM 更新后同步执行
用途 数据获取、订阅等副作用 需要同步读取/操作 DOM 的情况
对用户的影响 不会阻塞页面渲染 会阻塞页面渲染
使用频率 常用 特殊场景使用

7. 如何自定义 Hook?

自定义 Hook 是一个以 "use" 开头的函数,可以调用其他 Hook:

javascript 复制代码
function useCustomHook(initialValue) {
  const [value, setValue] = useState(initialValue);
  
  const doubleValue = useMemo(() => value * 2, [value]);
  
  const increment = useCallback(() => {
    setValue(v => v + 1);
  }, []);
  
  return { value, doubleValue, increment };
}

使用规则:

  1. 只在 React 函数组件或自定义 Hook 中调用 Hook
  2. 只在最顶层调用 Hook
  3. 自定义 Hook 必须以 "use" 开头

React 进阶知识

8. React 的 diff 算法原理是什么?

React 的 diff 算法基于两个假设:

  1. 不同类型的元素会产生不同的树
  2. 通过 key 属性标识稳定的子元素

优化策略:

  • Tree Diff:只比较同级节点,不跨级比较
  • Component Diff :
    • 相同类组件继续比较
    • 不同类组件直接替换
  • Element Diff :
    • 使用 key 标识元素
    • 移动而非重建相同 key 的元素

9. React 的性能优化手段有哪些?

  1. 使用 React.memo:缓存函数组件

    javascript 复制代码
    const MyComponent = React.memo(function MyComponent(props) {
      /* 使用 props 渲染 */
    });
  2. 使用 useMemo/useCallback:避免不必要的计算和渲染

  3. 避免内联函数和对象:防止子组件不必要重渲染

  4. 代码分割:

    javascript 复制代码
    const OtherComponent = React.lazy(() => import('./OtherComponent'));
  5. 虚拟化长列表:使用 react-window 或 react-virtualized

  6. 避免使用索引作为 key

  7. 使用 shouldComponentUpdate/PureComponent

10. React 的 Context 是什么?如何使用?

Context 提供了一种在组件树中共享值的方式,而不必显式地通过组件树的逐层传递 props。

创建 Context:

javascript 复制代码
const MyContext = React.createContext(defaultValue);

提供 Context:

javascript 复制代码
<MyContext.Provider value={/* 某个值 */}>
  {/* 子组件 */}
</MyContext.Provider>

消费 Context:

javascript 复制代码
// 类组件
static contextType = MyContext;
// 或
<MyContext.Consumer>
  {value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>

// 函数组件
const value = useContext(MyContext);

11. Redux 的核心概念和工作流程

核心概念:

  1. Store:保存应用状态的单一对象
  2. Action:描述发生什么的对象,必须有 type 字段
  3. Reducer:纯函数,接收旧 state 和 action,返回新 state
  4. Dispatch:触发 action 的方法

工作流程:

  1. 用户触发 UI 事件
  2. dispatch 一个 action
  3. reducer 根据 action 类型处理状态
  4. store 保存新状态
  5. 订阅 store 的组件重新渲染

Redux 三大原则:

  1. 单一数据源
  2. State 是只读的
  3. 使用纯函数修改 state

12. React Router 的核心概念和用法

核心组件:

  1. <BrowserRouter>:使用 HTML5 history API 的路由器
  2. <Route>:路由配置核心组件
  3. <Switch>:渲染第一个匹配的路由
  4. <Link>:导航链接
  5. <Redirect>:重定向

基本用法:

javascript 复制代码
<BrowserRouter>
  <Switch>
    <Route exact path="/" component={Home} />
    <Route path="/about" component={About} />
    <Route path="/users/:id" component={User} />
    <Redirect to="/" />
  </Switch>
</BrowserRouter>

Hooks API:

  • useHistory:访问 history 对象
  • useLocation:访问 location 对象
  • useParams:访问路由参数
  • useRouteMatch:访问匹配信息

React 实战问题

13. 如何解决 props 层层传递(prop drilling)问题?

  1. 使用 Context API:适合全局共享的数据
  2. 状态管理库:Redux、MobX 等
  3. 组件组合:通过 children 或 render props
  4. 状态提升:将共享状态提升到最近的共同祖先
  5. 自定义 Hooks:封装共享逻辑

14. React 中的错误边界是什么?

错误边界是捕获子组件树 JavaScript 错误的 React 组件:

javascript 复制代码
class ErrorBoundary extends React.Component {
  state = { hasError: false };
  
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
  
  componentDidCatch(error, info) {
    logErrorToService(error, info);
  }
  
  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children; 
  }
}

使用方式:

javascript 复制代码
<ErrorBoundary>
  <MyComponent />
</ErrorBoundary>

注意:

  • 无法捕获以下错误:
    • 事件处理函数
    • 异步代码
    • 服务端渲染
    • 错误边界自身抛出的错误

15. React 18 的新特性有哪些?

  1. 并发渲染(Concurrent Rendering):

    • 可中断渲染
    • 自动批处理更新
    • 过渡更新(startTransition)
  2. 新的 Root API:

    javascript 复制代码
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(<App />);
  3. 新的 Hooks:

    • useId:生成唯一 ID
    • useTransition:标记非紧急更新
    • useDeferredValue:延迟更新某些值
    • useSyncExternalStore:外部存储集成
    • useInsertionEffect:CSS-in-JS 库使用
  4. Suspense 增强:

    • 支持数据获取
    • 服务端流式渲染
  5. 改进的自动批处理:更多场景下的自动批处理

相关推荐
福兮说1 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理2 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆6662 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
Dovis(誓平步青云)3 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan3 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_4 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒4 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
广州华水科技4 小时前
大坝安全监测解决方案:单北斗GNSS形变监测系统应用与维护
前端
yivifu5 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub
默_笙5 小时前
🛴 从散件到整机:DeepAgents 与 Agent 身上预留的那些"插槽"(前置介绍)
前端·javascript