Next.js中useAsync钩子函数重复执行两次问题求助
解决useAsync钩子执行两次的问题
核心原因分析
- React Strict Mode 行为:Next.js在开发模式下默认启用Strict Mode,它会刻意重复执行
useEffect的回调函数,目的是检测代码中潜在的副作用问题,生产环境不会出现此情况。 - 依赖项触发重复执行:如果
useUser返回的user.id存在从undefined到有效值的变化,会导致useEffect的依赖项更新,进而触发第二次执行。
解决方案
方案1:利用Ref标记首次执行(解决开发环境重复执行)
在useAsync中添加一个Ref来跟踪是否已经完成首次执行,避免Strict Mode导致的重复调用:
import { useCallback, useEffect, useState, useRef } from "react"; import useUser from "./useUser"; export const useAsync = (func: Function, dependencies = [], requireAuth = true) => { const { execute, ...state } = useAsyncInternal(func, dependencies, true); const user = useUser(); const hasExecuted = useRef(false); useEffect(() => { // 已执行过则跳过 if (hasExecuted.current) return; if (requireAuth) { if (user.id) { execute(); hasExecuted.current = true; } } else { execute(); hasExecuted.current = true; } // 当user.id变为无值时重置标记,以便后续重新触发 return () => { if (!user.id) hasExecuted.current = false; }; }, [execute, user.id]); return state; } // useAsyncInternal 代码保持不变 const useAsyncInternal = (func: Function, dependencies = [], initialLoading = false) => { const [loading, setLoading] = useState(initialLoading); const [error, setError] = useState<any>(); const [data, setData] = useState<any>(); const execute = useCallback((...params: any[]) => { setLoading(true); return func(...params).then((data: any) => { setData(data); setError(undefined); return data; }).catch((error: any) => { setData(undefined); setError(error); return Promise.reject(error); }).finally(() => { setLoading(false); }); }, dependencies); return { loading, error, data, execute } }
方案2:调整Strict Mode配置(仅开发环境)
如果不需要Strict Mode的检测功能,可以在Next.js项目中关闭它:
- App Router:修改
next.config.js,添加reactStrictMode: false
/** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: false, }; module.exports = nextConfig;
- Pages Router:修改
pages/_app.tsx,移除<React.StrictMode>包裹
额外优化点
检查useAsyncInternal的initialLoading参数是否必要:当前设置为true会让loading初始状态为true,但并未触发函数执行,如果不需要初始loading状态,可以将调用时的第三个参数改为false,避免不必要的loading状态显示。
内容的提问来源于stack exchange,提问作者rockets4all
相关产品推荐
相关产品推荐

