当前位置: 首页 > 知识库问答 >
问题:

useEffect中的useState不更新状态

刘兴朝
2023-03-14

我不熟悉React钩子和React 16.13.1。

我将实现能够处理登录的Auth组件。

但是它似乎没有正确更新状态电流用户,即使setMONtUser使用响应对象调用。

这个代码有什么问题?

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"} />
  );
};

共有3个答案

龙玺
2023-03-14
匿名用户

因为@GermaneCobar已经应答了setCurrentUser异步更新状态。因此,您需要使用仅包含当前用户的依赖项列表来获得最新状态值。

然而,对于您的用例,您只关心当前用户是否真实,并基于此您希望将用户重定向到所需页面。因此,您不需要另一个useffect,因为您不会基于当前用户执行任何其他副作用。

在真实场景中,您希望显示加载/启动屏幕,直到您能够确定用户是否经过身份验证。因此,一旦异步任务完成,您应该将isload的初始值更改为true,并将状态更改为false。我建议您将州名称重命名为:

const[shouldCheckLogin,setShouldCheckLogin]=useState(true)

最后,!!null为false,而!!{}为true。对于对象的值,可以使用null初始化它们。

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

令狐宏浚
2023-03-14

由于React中设置状态的异步性质,调用状态设置器(setCurrentUser)可能会出现问题。我还没有找到任何明确的答案,当我使用React时,它是否与setState或sync异步。在我看来,在如此复杂的情况下,最好的解决方案就是使用类。它将为您提供许多使用钩子无法复制的生命周期方法,并且更适合于auth组件。React钩子并不是所有情况下类的替代品,它只是一种工具,允许您在只需要进行简单改进的同时不破坏现有代码。

锺离刚洁
2023-03-14

setCurrentUser以异步方式更新状态,因此之后不能立即使用。

但是,您可以使用另一个useffect来了解状态何时更改:

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

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

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

 类似资料:
  • 我正在构建一个制表符视图,我不明白为什么useState钩子没有更新我的状态。我肯定这是件容易的事,但我在这里已经被难住了一段时间... 我可以看到onPress函数已启动,如果我注销,则item.label是正确的。但是,即使我硬编码参数,setState也不会更改。

  • 我正在尝试使用注册功能组件中的useState更新组件的状态。当用户输入无效的电子邮件地址并单击“提交”按钮时,以下代码将返回错误消息 我想用这段代码将错误消息设置为formData。 如何将错误消息设置为formData? 这是我的密码:

  • 我有一个对象的状态数组: 我有一个添加按钮,用于将对象添加到数组中,这是onclick事件的主体:

  • 问题内容: 我正在尝试将事件发射器与React 和一起使用,但是它始终获取初始状态而不是更新状态。如果我直接调用事件处理程序(即使使用),也可以使用。 如果我将值传递给第二个参数,它将使其起作用,但是,每当值更改时(这是击键触发的),这都会导致事件发射器重新订阅。 我究竟做错了什么?我试过,,,和,并不能得到任何工作。 这是复制品: 这是具有相同代码的代码沙箱: https://codesandb

  • 我有一个功能组件,它用useState初始化一个状态,然后通过一个输入字段改变这个状态。 然后,我有一个useEffect钩子来模拟componentWillUnmount,以便在组件卸载之前,将当前更新的状态记录到控制台。但是,将记录初始状态,而不是当前状态。 这是我试图做的一个简单的表示(这不是我的实际组件): 我将状态初始化为“初始”然后我使用输入字段来改变状态,比如我键入“新文本”但是,当

  • 您可能知道,在正常模式下,当状态更新时,我们使用更新依赖项来获得通知,如下所示: 但在我的例子中,我的状态中有一个数组,我正在尝试在useEffect的循环中更新它,如下所示: 在本例中,每次forEach循环运行时,我都会得到初始val(我知道,因为val不是useffect的依赖项),但如果我将其作为依赖项,它将更新两次。解决这个问题的办法是什么? 编辑:基本上,我的意思是,当我在useffe