useEffect中的useState不会更新状态

时间:2020-10-04 06:52:48

标签: reactjs react-hooks

我是React Hooks的新手,正在使用react 16.13.1。

我将实现Auth组件,该组件可以处理登录。

但是,即使currentUser被响应对象调用,它似乎也无法正确更新状态setCurrentUser

此代码有什么问题?

import React, { useState, useEffect } from "react";
import { Route, Redirect } from "react-router-dom";
import { checkLoggedIn } from "utils/Api";

export const Auth = (props) => {
  const [currentUser, setCurrentUser] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  console.log(currentUser);

  useEffect(() => {
    const f = async () => {
      setIsLoading(true);
      console.log(isLoading);
      const res = await checkLoggedIn();
      if (!!res) { // ==> true
        setCurrentUser(res);
        console.log(currentUser); // ==> null!
      }
      setIsLoading(false);
    };
    f();
  });

  if (isLoading) {
    return <div>loading</div>;
  }

  console.log(currentUser); // ==> null!
  return !!currentUser ? (
    <Route children={props.children} />
  ) : (
    <Redirect to={"/login"} />
  );
};

4 个答案:

答案 0 :(得分:4)

setCurrentUser异步更新状态,因此之后不能立即使用currentUser

但是,您可以使用另一个useEffect来知道何时更改状态:

useEffect(() => {
  // currentUser changed
}, [currentUser])

我还注意到,您没有将空数组传递给您已经拥有的useEffect,因此它将在每次组件更新时触发。如果您只需要执行一次useEffect,则必须将空数组作为第二个参数传递,如下所示:

  useEffect(() => {
    const f = async () => {
      // ...
    };
    f();
  }, []);

答案 1 :(得分:2)

由于在React中设置状态的异步特性,调用状态的setter(setCurrentUser)可能是一个问题。我还没有找到任何明确的答案,当我使用React时,它是作为setState异步还是同步。我认为,在这种复杂情况下的最佳解决方案就是使用类。它会为您提供许多生命周期方法,这些方法无法使用钩子重现,并且将更适合auth组件。 React Hooks并不是在所有情况下都可以替代类,而只是一种工具,使您在需要进行简单的改进时就不会破坏现有的代码。

答案 2 :(得分:2)

@germanescobar已回答setCurrentUser,因此异步更新状态。因此,您需要useEffect的依赖项列表仅包含currentUser才能获取最新的状态值。

但是,对于您的用例,您仅对currentUser是否真实感兴趣,并希望以此为基础将用户重定向到所需页面。因此,您不需要其他useEffect,因为您不会基于currentUser执行任何其他副作用。

在实际情况下,您想要显示加载/启动屏幕,直到您能够确定用户是否通过身份验证为止。因此,异步任务完成后,应将isLoading的初始值更改为true,并将状态更改为false。我建议您将州名重命名为:

const [shouldCheckLogin, setShouldCheckLogin] = useState(true)

最后,!!nullfalse,而!!{}true。对于object的值,最好使用null初始化它们。

console.log(!!null)
console.log(!!{})

答案 3 :(得分:1)

感谢@germanescobar和@Vadim教给我很多东西!

我现在注意到useState的参数与此问题有关。

改变

const [currentUser, setCurrentUser] = useState(null);

进入

const [currentUser, setCurrentUser] = useState({});

似乎已经解决了未更新的问题(尽管我不知道原因)。