useEffect的奇怪行为

时间:2019-12-30 17:13:30

标签: javascript reactjs axios react-hooks

我正在使用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);
  });
}

发生的是,当我只希望一次调用该请求时,该请求将被调用多次。

enter image description here

如您在上面的屏幕快照中所见,在5个请求中,其中一个成功,其他失败,我不确定是什么引起的。任何想法都会有所帮助。

2 个答案:

答案 0 :(得分:5)

您可能需要将一个空数组([])添加为钩子的第二个参数。它阻止挂钩多次运行。

数组应该包含变量(通常是组件状态的一部分),如果钩子发生更改,钩子应该监视并重新运行它们。 变量对于钩子所做的任何事情都至关重要。

假设您的钩子应该显示某个类别中某个youtube频道的订阅者数量-假设类别是A,B和C(假设),用户可以在其中进行切换要查看的类别可能使用下拉菜单;那么该数组将包含 category 变量,以便每当更改时,该钩子就会运行以获取该类别中的订户数量。使数组为空是一种告诉 React 的方法,您没有依赖性,并且可以确定钩子首次运行时的功能。

反应比较该数组中的值以获取每个渲染的更改,如果不更改,则跳过该挂钩。如果您将其保留为空,则值将永远不会改变,这意味着该挂钩将运行一次,然后在随后的重新渲染时被跳过。

答案 1 :(得分:2)

您的useEffect挂钩在每个渲染器上运行。由于您在请求完成后调用setIsErrorsetLoggedIn,所以这将触发另一个渲染以及另一个渲染,等等。老实说,我很惊讶没有无限循环。要解决此问题,请尝试使其仅在之前未尝试登录时才尝试登录(没有错误且当前未登录。)像这样:

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

如果您确定只希望它运行一次(在第一个渲染器上),请为它提供一个空的依赖项数组,这样它就永远不会再次运行。