如何在另一个自定义Hook中使用一个返回值的自定义Hook?
回答 2
浏览 5775
2021-12-29
我正在使用React-native,在其中,我有一个名为useUser
的自定义Hook,它使用Auth.getUserInfro
方法从AWS Amplify获取用户信息,然后获取返回对象的一部分并将其设置为一个状态变量。我还有一个叫做useData
的Hook,它根据userId来获取一些数据,并将其设置为一个状态变量。
useUser自定义钩子:
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
}
当我试图这样做的时候,我得到一个错误,告诉我
*Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- 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.*
我认为问题在于我在使用效果里面调用了Hook useUser,但是在函数里面使用它将导致这里描述的问题,而且我不能在fetchData
的主体之外使用它,因为useData
本身是一个钩子,它只能在一个功能组件或Hook的主体里面使用。所以我不知道如何找到一个解决这个问题的方法。
为什么你坚持要把简单的获取包在一个钩子里呢? 只要在useData钩子里调用getUserInfo就可以了。
- HDM91 2021-12-29
我不明白为什么你不能在useData的主体中使用useUser?
- HDM91 2021-12-29
2 个回答
#1楼
已采纳
得票数 3
正确,React钩子只能从React函数组件和其他React钩子调用。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;
};
#2楼
得票数 0
你不能在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;
};