与异步自定义反应挂钩作斗争。如何等待一个钩子的结果以在另一个钩子中使用?

Wes*_*n S 2 javascript promise reactjs react-hooks react-query

我在使用自定义反应挂钩方面遇到了一些困难。

我有 2 个定制挂钩。

第一个钩子用于获取 ID,第二个钩子用于使用先前获取的 ID 来获取配置文件。它依赖于该 ID,所以我需要等待这个承诺。

我有以下自定义挂钩:

export const UseMetamask = () => {

    //Todo: Create check if metamask is in browser, otherwise throw error
    const fetchWallet = async (): Promise<string | null> => {
        try {
            const accounts: string[] = await window.ethereum.request(
                {
                    method: 'eth_requestAccounts'
                },
            );

            return accounts[0];

        } catch(e) {
            console.error(e);

            return null;
        }
    }
    
    return fetchWallet();
}
Run Code Online (Sandbox Code Playgroud)

然后在我的第二个钩子中我有:

const wallet = UseMetamask();
Run Code Online (Sandbox Code Playgroud)

然后在反应查询调用中使用它,例如:

useQuery(
    ['user', wallet],
    () => getUserByWallet(wallet),
Run Code Online (Sandbox Code Playgroud)

现在它抱怨钱包说它是一个Promise<string | null>当然不适合的getUserByWallet

等待另一个钩子然后在第二个钩子中使用该结果的方法是什么?

谢谢!

Ori*_*ori 5

功能组件是一个同步函数,并且作为组件具有生命周期钩子。异步调用是应该由钩子处理的副作用,而不是通过在函数体中传递 Promise 来处理。请参阅此答案

选项 1 -useEffect与 一起使用useState

封装 api 调用useEffect并设置walletapi 调用成功时的状态。wallet从钩子返回状态:

export const useMetamask = () => {
  const [wallet, setWallet] = useState<string | null>(null);
  
  useEffect(() => {
    const fetchWallet = async(): Promise<string | null> => {
      try {
        const accounts: string[] = await window.ethereum.request({
          method: 'eth_requestAccounts'
        });

        setWallet(accounts[0]);

      } catch (e) {
        console.error(e);

        return null;
      }
    }
    
    fetchWallet();
  }, []);

  return wallet;
}
Run Code Online (Sandbox Code Playgroud)

用法:

wallet从钩子上取下来。这将是null或实际值:

const wallet = useMetamask();
Run Code Online (Sandbox Code Playgroud)

仅当 a实际存在(不是)enable时调用。我们将使用该选项(请参阅依赖查询),根据以下值启用/禁用查询:walletnullenablewallet

useQuery(
  ['user', wallet],
  () => getUserByWallet(wallet),
  {
  // The query will not execute until the wallet exists
  enabled: !!wallet,
  }
)
Run Code Online (Sandbox Code Playgroud)

选项 2 - 使用两个useQuery钩子

由于您已经使用了useQuery,因此您需要编写一个自定义挂钩。wallet只需从另一个电话中获取useQuery

const wallet = useQuery('wallet', fetchWallet);

useQuery(
  ['user', wallet],
  () => getUserByWallet(wallet),
  {
  // The query will not execute until the wallet exists
  enabled: !!wallet,
  }
)
Run Code Online (Sandbox Code Playgroud)