如何在另一个自定义 Hook 中使用 returns 一个值的自定义 hook?

How to use a custom-hook that returns a value, inside another custom Hook?

我正在使用 React-native,在其中,我有一个名为 useUser 的自定义 Hook,它使用 Auth.getUserInfro 方法从 AWS Amplify 获取用户信息,然后获取返回的部分信息对象并用它设置一个状态变量。我还有另一个名为 useData 的 Hook,它根据 userId 获取一些数据并将其设置为状态变量。

使用用户自定义挂钩:

import React, { useState, useEffect } from "react";
import { Auth } from "aws-amplify";

const getUserInfo = async () => {
  try {
    const userInfo = await Auth.currentUserInfo();
    const userId = userInfo?.attributes?.sub;
    return userId;
  } catch (e) {
    console.log("Failed to get the  AuthUserId", e);
  }
};

const useUserId = () => {
  const [id, setId] = useState("");

  useEffect(() => {
    getUserInfo().then((userId) => {
      setId(userId);
    });
  }, []);

  return id;
};

export default useUserId;
import useUserId from "./UseUserId";
// ...rest of the necessary imports

const fetchData = async (userId) = > { // code to fetch data from GraphQl}

const useData = () => {
    const [data, setData] = useState();
    
    useEffect(() => { 
        const userId = useUser();
        fetchData(userId).then( // the rest of the code to set the state variable data.)
    },[])

    return data
   }

当我尝试这样做时,我收到一条错误提示

*错误:挂钩调用无效。钩子只能在函数组件的主体内部调用。这可能由于以下原因之一而发生:

  1. 您的 React 和渲染器版本可能不匹配(例如 React DOM)
  2. 您可能违反了 Hooks 规则
  3. 您可能在同一个应用程序中拥有多个 React 副本 有关如何调试和修复此问题的提示,请参阅 https://reactjs.org/link/invalid-hook-call。*

我觉得问题是我在use effect内部调用了Hook useUser,但是在函数内部使用会出现描述的问题,在body外部无法使用fetchData 的,因为 useData 本身是一个钩子,它只能在功能组件或钩子的内部使用。所以我不知道如何找到解决这个问题的方法。

正确,React hooks只能从React函数组件和其他React hooks调用。 useEffect 钩子的回调不是 React 钩子,它是一个回调。根据 Rules of Hooks,不要在循环、条件或嵌套函数中调用钩子。

我建议重构 useData 挂钩以使用 userId 作为参数,用于 useEffect.

的依赖数组
const fetchData = async (userId) => {
  // code to fetch data from GraphQl
};

const useData = (userId) => {
  const [data, setData] = useState();
    
  useEffect(() => { 
    fetchData(userId)
      .then((....) => {
        // the rest of the code to set the state variable data.
      });
  }, [userId]);

  return data;
};

函数组件中的用法:

const userId = useUser();
const data = useData(userId);

如果这是通常配对的东西,抽象成一个钩子:

const useGetUserData = () => {
  const userId = useUser();
  const data = useData(userId);
  return data;
};

...

const data = useGetUserData();

尽管您可能应该按如下方式实现单个挂钩:

const useGetUserData = () => {
  const [data, setData] = useState();

  useEffect(() => {
    getUserInfo()
      .then(fetchData) // shortened (userId) => fetchData(userId)
      .then((....) => {
        // the rest of the code to set the state variable data.
        setData(....);
      });
  }, []);

  return data;
};

你不能在 useEffect 中调用 hook,Hook 应该总是在组件体内,而不是在内部 function/hook 体内。

import useUserId from "./UseUserId";
// ...rest of the necessary imports

const fetchData = async (userId) => {
  // code to fetch data from GraphQl}
};
const useData = () => {
  const [data, setData] = useState();
  const userId = useUser();
  useEffect(() => {
    if (userId) {
      fetchData(userId).then(setData);
    }
  }, [userId]);

  return data;
};