简体   繁体   English

如何在另一个自定义挂钩中使用返回值的自定义挂钩?

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

I am using React-native and in it, I have a custom Hook called useUser that gets the user's information from AWS Amplify using the Auth.getUserInfro method, and then gets part of the returned object and sets a state variable with it.我正在使用 React-native,在其中,我有一个名为useUser的自定义 Hook,它使用Auth.getUserInfro方法从 AWS Amplify 获取用户信息,然后获取返回的 object 的一部分,并使用它设置一个 Z9ED39E25EA931586B76E9 变量。 I also have another Hook called useData hook that fetches some data based on the userId and sets it to a state variable.我还有另一个名为useData的 Hook,它根据 userId 获取一些数据并将其设置为 state 变量。

useUser custom-Hook:使用用户自定义-Hook:

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
   }

When I try to do this I get an error telling me当我尝试这样做时,我收到一条错误消息告诉我

*Error: Invalid hook call. *错误:无效的挂钩调用。 Hooks can only be called inside of the body of a function component.钩子只能在 function 组件的主体内部调用。 This could happen for one of the following reasons:这可能由于以下原因之一而发生:

  1. You might have mismatching versions of React and the renderer (such as React DOM)你可能有不匹配的 React 版本和渲染器(例如 React DOM)
  2. You might be breaking the Rules of Hooks您可能违反了 Hooks 规则
  3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.*您可能在同一个应用程序中拥有多个 React 副本,请参阅https://reactjs.org/link/invalid-hook-call以获取有关如何调试和修复此问题的提示。*

I think the problem is that I am calling the Hook useUser inside of the use effect, but using it inside the function will cause the problem described here , and I can't use it outside the body of the fetchData since the useData itself is a hook, and it can be only used inside a functional component's or Hook's body.我认为问题在于我在 use 效果内部调用了 Hook useUser,但是在 function 内部使用它会导致这里描述的问题,并且我不能在fetchData的主体之外使用它,因为useData本身是一个hook,只能在函数式组件或 Hook 体内使用。 So I don't know how to find a way around this problem.所以我不知道如何找到解决这个问题的方法。

Correct, React hooks can only be called from React function components and other React hooks.正确,React 钩子只能从 React function 组件和其他 React 钩子中调用。 The useEffect hook's callback isn't a React hook, it's a callback. useEffect钩子的回调不是 React 钩子,它是一个回调。 According to the Rules of Hooks , don't call hooks inside loops, conditions, or nested functions.根据钩子规则,不要在循环、条件或嵌套函数中调用钩子。

I suggest refactoring the useData hook to consume the userId as an argument, to be used in the dependency array of the useEffect .我建议重构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;
};

Usage in Function component: Function 组件中的用法:

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

If this is something that is commonly paired, abstract into a single hook:如果这是通常配对的东西,请抽象成一个钩子:

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

... ...

const data = useGetUserData();

Though you should probably just implement as a single hook as follows:尽管您可能应该将其实现为单个钩子,如下所示:

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;
};

You can't call hook inside useEffect, Hook should be always inside componet body not inside inner function/hook body.你不能在 useEffect 中调用钩子,钩子应该总是在组件体内,而不是在内部函数/钩子体内。

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;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM