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,使其在首次渲染时不执行,但在后续依赖变化时执行,并且在组件卸载时执行清理逻辑。

相关推荐
wuhen_n18 分钟前
网络请求在Vite层的代理与Mock:告别跨域和后端依赖
前端·javascript·vue.js
用户69371750013845 小时前
Google 正在“收紧侧加载”:陌生 APK 安装或需等待 24 小时
android·前端
蓝帆傲亦5 小时前
Web 前端搜索文字高亮实现方法汇总
前端
用户69371750013845 小时前
Room 3.0:这次不是升级,是重来
android·前端·google
漫随流水7 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
踩着两条虫8 小时前
VTJ.PRO 核心架构全公开!从设计稿到代码,揭秘AI智能体如何“听懂人话”
前端·vue.js·ai编程
jzlhll1239 小时前
kotlin Flow first() last()总结
开发语言·前端·kotlin
用头发抵命9 小时前
Vue 3 中优雅地集成 Video.js 播放器:从组件封装到功能定制
开发语言·javascript·ecmascript
蓝冰凌10 小时前
Vue 3 中 defineExpose 的行为【defineExpose暴露ref变量】详解:自动解包、响应性与实际使用
前端·javascript·vue.js
奔跑的呱呱牛10 小时前
generate-route-vue基于文件系统的 Vue Router 动态路由生成工具
前端·javascript·vue.js