React异步自定义Hook调用问题:如何等待一个Hook结果再用另一个?
解决方案:正确处理自定义Hook中的异步逻辑
你的核心问题在于第一个自定义Hook直接返回了Promise,而React组件渲染是同步的,无法直接等待Promise完成后再执行后续逻辑。正确的做法是在Hook内部用状态管理异步结果,配合React Query的enabled选项控制查询时机。
步骤1:重构第一个自定义Hook
把异步请求的结果存在state里,同时暴露加载状态,让调用方知道什么时候数据准备好:
import { useState, useEffect } from 'react'; export const useMetamask = () => { // 注意Hook命名规范:小写开头+use前缀 const [wallet, setWallet] = useState<string | null>(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState<Error | null>(null); useEffect(() => { const fetchWallet = async () => { try { // 先检查Metamask是否存在 if (!window.ethereum) { throw new Error('Metamask未安装'); } const accounts: string[] = await window.ethereum.request({ method: 'eth_requestAccounts' }); setWallet(accounts[0]); } catch (e) { const err = e as Error; console.error(err); setError(err); setWallet(null); } finally { setIsLoading(false); } }; fetchWallet(); }, []); return { wallet, isLoading, error }; };
步骤2:在React Query中依赖异步结果
使用重构后的Hook,通过enabled选项让React Query只在wallet有值时才发起请求:
import { useQuery } from '@tanstack/react-query'; import { useMetamask } from './useMetamask'; // 第二个自定义Hook或组件中使用 export const useUserByWallet = () => { const { wallet, isLoading: isWalletLoading, error: walletError } = useMetamask(); const { data: user, isLoading: isUserLoading, error: userError } = useQuery({ queryKey: ['user', wallet], queryFn: () => getUserByWallet(wallet!), // wallet有值时才执行,所以用!断言 enabled: !!wallet, // 只有wallet不为null/undefined时才触发查询 retry: false // 可选:如果wallet获取失败,不需要重试查询 }); return { user, isLoading: isWalletLoading || isUserLoading, error: walletError || userError }; };
关键说明
- Hook命名规范:React官方要求Hook必须以
use开头且小写字母起始,所以把UseMetamask改成useMetamask。 - 状态管理异步结果:用
useState存储wallet、加载状态和错误,useEffect触发异步请求,确保组件渲染时能同步获取当前状态。 - React Query的enabled选项:这是控制依赖异步数据查询的核心,只有当依赖的
wallet存在时,才执行getUserByWallet请求,避免传入Promise或无效值。
内容的提问来源于stack exchange,提问作者Wesley van S
相关产品推荐
相关产品推荐

