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>;
}
相关推荐
LaughingZhu4 小时前
Product Hunt 每日热榜 | 2026-05-21
前端·人工智能·经验分享·chatgpt·html
怕浪猫4 小时前
Electron 开发实战(一):从零入门核心基础与环境搭建
前端·electron·ai编程
小鹏linux5 小时前
Ubuntu 22.04 部署开源免费具有精美现代web页面的Casdoor账号管理系统
linux·前端·ubuntu·开源·堡垒机
前端若水6 小时前
会话管理:创建、切换、删除对话历史
前端·人工智能·python·react.js
Bigger6 小时前
mini-cc:一个轻量级 AI 编程助手的诞生
前端·ai编程·claude
涵涵(互关)6 小时前
Naive-ui树型选择器只显示根节点
前端·ui·vue
BY组态6 小时前
Ricon组态系统最佳实践:从零开始构建物联网监控平台
前端·物联网·iot·web组态·组态
BY组态6 小时前
Ricon组态系统vs传统组态软件:为什么选择新一代Web组态平台
前端·物联网·iot·web组态·组态
SoaringHeart6 小时前
Flutter进阶:OverlayEntry 插入图层管理器 NOverlayZIndexManager
前端·flutter
放下华子我只抽RuiKe57 小时前
React 从入门到生产(四):自定义 Hook
前端·javascript·人工智能·深度学习·react.js·自然语言处理·前端框架