effect 副作用相关

useUpdateEffect

useUpdateEffect 用法等同于 useEffect,但是会忽略首次执行,只在依赖更新时执行。

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

const useUpdateEffect: typeof useEffect = (effect, deps) => {
  const isMounted = useRef(false);

  // 首次渲染后标记为已挂载
  useEffect(() => {
    isMounted.current = true;
    
    // 组件卸载时重置标志
    return () => {
      isMounted.current = false;
    };
  }, []);

  // 实际的 effect,只有在已挂载且依赖项变化时才执行
  useEffect(() => {
    if (isMounted.current) {
      return effect();
    }
  }, deps);
};

export default useUpdateEffect;

useUpdateLayoutEffect

useUpdateLayoutEffect 用法等同于 useLayoutEffect,但是会忽略首次执行,只在依赖更新时执行。

js 复制代码
import { useLayoutEffect, useRef } from 'react';

const useUpdateLayoutEffect: typeof useLayoutEffect = (effect, deps) => {
  const isMounted = useRef(false);

  // 首次渲染后标记为已挂载
  useLayoutEffect(() => {
    isMounted.current = true;
    
    // 组件卸载时重置标志
    return () => {
      isMounted.current = false;
    };
  }, []);

  // 实际的 layout effect,只有在已挂载且依赖项变化时才执行
  useLayoutEffect(() => {
    if (isMounted.current) {
      return effect();
    }
  }, deps);
};

export default useUpdateLayoutEffect;
js 复制代码
// 使用场景:DOM 同步测量和调整
import { useUpdateLayoutEffect } from 'ahooks';

function ResponsiveComponent({ items }) {
  const containerRef = useRef(null);
  
  // 需要在 DOM 更新后立即测量并调整样式
  useUpdateLayoutEffect(() => {
    const container = containerRef.current;
    if (container) {
      // 测量容器尺寸
      const { width } = container.getBoundingClientRect();
      
      // 根据宽度调整子元素样式(需同步执行避免闪烁)
      const children = container.querySelectorAll('.item');
      children.forEach(child => {
        child.style.flexBasis = width > 600 ? '50%' : '100%';
      });
    }
  }, [items]);
  
  return (
    <div ref={containerRef}>
      {items.map(item => (
        <div key={item.id} className="item">
          {item.content}
        </div>
      ))}
    </div>
  );
}

useAsyncEffect

useEffect 支持异步函数

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

const useAsyncEffect = (
  effect: (isCanceled: () => boolean) => Promise<void | (() => void)>,
  deps?: React.DependencyList
) => {
  const isCanceledRef = useRef(false);
  
  useEffect(() => {
    isCanceledRef.current = false;
    
    // 执行异步效应
    const result = effect(() => isCanceledRef.current);
    
    // 返回清理函数
    return () => {
      isCanceledRef.current = true;
      
      // 如果 effect 返回了 Promise,处理其结果
      if (result instanceof Promise) {
        result.then(cleanup => {
          if (cleanup && !isCanceledRef.current) {
            cleanup();
          }
        });
      }
    };
  }, deps);
};

export default useAsyncEffect;
js 复制代码
// 使用场景:异步数据获取
import { useAsyncEffect } from 'ahooks';
import { useState } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useAsyncEffect(async (isCanceled) => {
    setLoading(true);
    
    try {
      const response = await fetch(`/api/users/${userId}`);
      const userData = await response.json();
      
      // 检查是否已取消,避免在组件卸载后设置状态
      if (!isCanceled()) {
        setUser(userData);
        setLoading(false);
      }
    } catch (error) {
      if (!isCanceled()) {
        console.error('Failed to fetch user:', error);
        setLoading(false);
      }
    }
  }, [userId]);
  
  if (loading) return <div>Loading...</div>;
  return <div>Hello, {user?.name}!</div>;
}
相关推荐
Nymph_Zhu20 分钟前
pdf转换markdown预览及内容互相点击定位
前端·pdf·vue3·markdown·element-plus
计算机魔术师24 分钟前
Google 一天蒸发5000亿,Reddit 靠 AI 训练喂得饱自己却饿死
前端
小大宇31 分钟前
Vue知识点-ElementPlus-05 输入框
前端·javascript·vue.js
l1m0_1 小时前
AI设计工具有哪些?Paico、Pixso AI、墨刀AI、Lovable、Codex怎么选
前端·人工智能·ai·设计·墨刀·codex·pixso
web打印社区1 小时前
Lodop在Edge和双核浏览器-先分清内核
前端·javascript·edge·pdf·ecmascript·html5
西瓜拿铁好喝1 小时前
开源和闭源 AI 办公工具,分别适合谁
java·前端·数据库
IT_陈寒1 小时前
深入理解SpringBoot:核心原理与最佳实践
前端·人工智能·后端
风骏时光牛马1 小时前
大模型综合能力多维评测:性能、逻辑与落地表现对比
前端
liuchangng2 小时前
React 19 + Vite 6 实战:从教材 PDF 到 866 词间隔重复单词 App
前端·react.js·pdf·vite·开源项目
Dwzun2 小时前
基于SpringBoot3+Vue3的油莎豆种植管理系统
java·前端·vue.js·spring boot·后端·python·计算机网络