React面试题,封装useEffect

在React中,useEffect 是一个非常常用的钩子,用于处理副作用(如数据获取、订阅或手动更改 DOM)。默认情况下,useEffect 在组件首次渲染时和每次依赖项变化时都会执行。如果你希望封装一个 useEffect,使其在第一次渲染时不执行,可以通过一个自定义钩子来实现。

自定义钩子:useEffectSkipFirst

tsx 复制代码
import { useEffect, useRef } from 'react';

// 自定义钩子,跳过第一次执行,支持清理逻辑
function useEffectSkipFirst(effect: () => void | (() => void), dependencies: any[] = []) {
  const skipFirst = useRef(true); // 使用 useRef 来存储是否跳过第一次的状态

  useEffect(() => {
    if (skipFirst.current) {
      skipFirst.current = false; // 第一次时跳过,并将状态改为 false
      return undefined; // 不执行任何操作
    }

    // 执行传入的副作用函数
    const cleanup = effect();

    // 如果副作用函数返回了一个清理函数,则在组件卸载或依赖变化时执行清理逻辑
    return cleanup;
  }, dependencies); // dependencies 是依赖项数组
}

export default useEffectSkipFirst;

使用方法

tsx 复制代码
import React from 'react';
import useEffectSkipFirst from './useEffectSkipFirst';

const MyComponent = () => {
  useEffectSkipFirst(() => {
    console.log('This effect will not run on the first render');

    // 返回清理逻辑
    return () => {
      console.log('Cleanup logic executed on component unmount or dependency change');
    };
  }, []); // 依赖项为空数组,表示只在依赖项变化时执行

  return <div>My Component</div>;
};

export default MyComponent;

工作原理

  1. useRefuseRef 创建一个可变的引用对象,其值在组件的整个生命周期内保持不变。这里用它来存储一个布尔值 skipFirst,初始值为 true
  2. useEffect
    • useEffect 中,首先检查 skipFirst.current 的值:
      • 如果是 true,说明是第一次渲染,直接跳过,并将 skipFirst.current 设置为 false
      • 如果是 false,说明不是第一次渲染,执行传入的副作用函数 effect
    • 如果 effect 返回了一个清理函数(即返回值是一个函数),则在组件卸载或依赖项变化时执行该清理函数。
  3. 依赖项dependencies 数组用于控制 useEffect 的执行时机,与普通 useEffect 的行为一致。

示例解释

  • 首次渲染skipFirst.currenttrue,跳过执行 effect,不执行任何操作。
  • 后续依赖变化skipFirst.currentfalse,执行 effect,并返回清理函数(如果有)。
  • 组件卸载 :当组件卸载时,useEffect 的返回值(清理函数)会被执行,确保资源被正确清理。

注意事项

  • 确保 effect 函数的返回值是一个函数,否则清理逻辑不会被触发。
  • 如果依赖项数组为空([]),则副作用函数只会在组件首次渲染后和组件卸载时执行。
  • 如果依赖项数组中有值,则副作用函数会在依赖项变化时执行,并在组件卸载时执行清理逻辑。

通过这种方式,你可以实现一个自定义的 useEffect,使其在首次渲染时不执行,但在后续依赖变化时执行,并且在组件卸载时执行清理逻辑。

相关推荐
于慨21 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz21 小时前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
从前慢丶21 小时前
前端交互规范(Web 端)
前端
@yanyu6661 天前
07-引入element布局及spring boot完善后端
javascript·vue.js·spring boot
CHU7290351 天前
便捷约玩,沉浸推理:线上剧本杀APP功能版块设计详解
前端·小程序
GISer_Jing1 天前
Page-agent MCP结构
前端·人工智能
王霸天1 天前
💥别再抄网上的Scale缩放代码了!50行源码教你写一个永不翻车的大屏适配
前端·vue.js·数据可视化
小领航1 天前
用 Three.js + Vue 3 打造炫酷的 3D 行政地图可视化组件
前端·github
@大迁世界1 天前
2026年React大洗牌:React Hooks 将迎来重大升级
前端·javascript·react.js·前端框架·ecmascript
PieroPc1 天前
一个功能强大的 Web 端标签设计和打印工具,支持服务器端直接打印到局域网打印机。Fastapi + html
前端·html·fastapi