React useAuth Hook无限循环问题:Hook与Context实现差异解析
问题:useAuth Hook两种实现的行为差异原因
原始Hook实现(存在无限循环)
const useApiCall = () => { return useQuery({ queryKey: ["/load"], queryFn: async () => { const resp = await fetch( "https://api.publicapis.org/entries" ).then((response) => response.json()); return resp.entries; } }); }; function useAuth() { const { data: user = null, isLoading, isFetching, error, refetch } = useApiCall(); return useMemo( () => ({ user, isLoading: isLoading || isFetching, authenticated: !user && !isFetching && !isLoading, error, refetch }), [user, isLoading, isFetching, error, refetch] ); }
在多个组件中调用该Hook时,会出现无限循环问题。
Context方式实现(无循环问题)
const AuthProvider = ({ children }) => { const { data: user = null, isLoading, isFetching, error, refetch } = useMe(); const values = useMemo( () => ({ user, isLoading: isLoading || isFetching, authenticated: user && !isFetching && !isLoading, error, refetch }), [ user, isLoading, isFetching, error, refetch ] ); return <AuthContext.Provider value={values}>{children}</AuthContext.Provider>; }; const useAuth = () => { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth must be used within the AuthProvider'); } return context; };
多处调用useAuth时无循环问题。
差异原因解释
重复请求触发重渲染循环
原始实现里,每调用一次useAuth就会创建一个独立的useQuery实例(因为useApiCall内部调用useQuery)。多个组件调用useAuth时,相当于同时发起了多个相同的请求,每个请求完成后会更新对应组件的状态,触发组件重渲染;重渲染又会再次调用useAuth发起新请求,形成无限循环。Context实现单一数据源,避免重复请求
Context方式中,数据请求逻辑只在AuthProvider中执行一次,整个上下文内只有一个useQuery实例。所有调用useAuth的组件共享同一个Context状态,请求只会发起一次,状态更新时所有依赖组件统一重渲染,不会重复触发请求,自然不会产生循环。状态作用域不同
原始Hook的状态是组件级的,每个调用useAuth的组件都持有独立的状态副本;而Context实现的状态是上下文级的,所有子组件共享同一状态,从根源上避免了重复请求和状态不一致导致的循环。
内容的提问来源于stack exchange,提问作者Bobo
相关产品推荐
相关产品推荐

