我正在使用react hooks建立一个项目。我的useEffect
函数如下所示...
useEffect(() => {
(async function() {
const queryParams = await qs.parse(props.location.search, { ignoreQueryPrefix: true }).code;
if (queryParams != undefined) {
setCode(queryParams);
postLogin();
}
})();
});
postLogin
函数只是使用上面定义的查询参数向服务器发出的GET
请求。看起来如此……
const postLogin = async () => {
await axios.get("http://XXX.XXX.X.XX:52805/user/auth", {
params: {
auth_code: code
}
}).then(result => {
setAuthTokens(result.data.credentials.access_token);
setLoggedIn(true);
}).catch(e => {
setIsError(true);
});
}
发生的是,当我只希望一次调用该请求时,该请求将被调用多次。
如您在上面的屏幕快照中所见,在5个请求中,其中一个成功,其他失败,我不确定是什么引起的。任何想法都会有所帮助。
答案 0 :(得分:5)
您可能需要将一个空数组([]
)添加为钩子的第二个参数。它阻止挂钩多次运行。
数组应该包含变量(通常是组件状态的一部分),如果钩子发生更改,钩子应该监视并重新运行它们。 变量对于钩子所做的任何事情都至关重要。
假设您的钩子应该显示某个类别中某个youtube频道的订阅者数量-假设类别是A,B和C(假设),用户可以在其中进行切换要查看的类别可能使用下拉菜单;那么该数组将包含 category 变量,以便每当更改时,该钩子就会运行以获取该类别中的订户数量。使数组为空是一种告诉 React 的方法,您没有依赖性,并且可以确定钩子首次运行时的功能。
反应比较该数组中的值以获取每个渲染的更改,如果不更改,则跳过该挂钩。如果您将其保留为空,则值将永远不会改变,这意味着该挂钩将运行一次,然后在随后的重新渲染时被跳过。
答案 1 :(得分:2)
您的useEffect
挂钩在每个渲染器上运行。由于您在请求完成后调用setIsError
或setLoggedIn
,所以这将触发另一个渲染以及另一个渲染,等等。老实说,我很惊讶没有无限循环。要解决此问题,请尝试使其仅在之前未尝试登录时才尝试登录(没有错误且当前未登录。)像这样:
useEffect(async () => {
if (isLoggedIn || isError) return; // Don't try again if a request has already succeeded or failed.
// Optionally use "isLoggedIn || isError || isLoading" to prevent multiple concurrent requests,
// which may cause further re-rendering.
const queryParams = await qs.parse(props.location.search, { ignoreQueryPrefix: true }).code;
if (queryParams != undefined) {
setCode(queryParams);
postLogin();
}
});
如果您确定只希望它运行一次(在第一个渲染器上),请为它提供一个空的依赖项数组,这样它就永远不会再次运行。