我是第一次接触React Hooks和使用react 16.13.1。
我将实现Auth组件,它可以处理登录。
但是,即使使用response Object调用setCurrentUser,它似乎也没有正确更新状态currentUser。
这段代码有什么问题?
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"} />
);
};发布于 2020-10-04 15:07:56
setCurrentUser异步地更新状态,因此您不能在之后立即使用currentUser。
但是,您可以使用另一个useEffect来了解状态更改的时间:
useEffect(() => {
// currentUser changed
}, [currentUser])我还注意到,您没有将空数组传递给已有的useEffect,因此它将在组件每次更新时触发。如果您只需要执行一次useEffect,则必须传递一个空数组作为第二个参数,如下所示:
useEffect(() => {
const f = async () => {
// ...
};
f();
}, []);发布于 2020-10-04 15:40:40
因为@germanescobar已经响应了,所以setCurrentUser异步更新状态。因此,您需要使用仅包含currentUser的依赖项列表进行useEffect,以获取最新的状态值。
但是,对于您的用例,您只对currentUser是否真实感兴趣,并基于此将用户重定向到所需的页面。因此,您不需要另一个useEffect,因为您不会基于currentUser执行任何其他副作用。
在实际场景中,您希望显示加载/启动屏幕,直到您能够确定用户是否通过身份验证。因此,您应该将isLoading的初始值更改为true,并在完成异步任务后将状态更改为false。我建议您将州名称重命名为类似如下的名称:
const [shouldCheckLogin, setShouldCheckLogin] = useState(true)。
最后,!!null是false,而!!{}是true。对于object的值,用null初始化它们是完全可以的。
console.log(!!null)
console.log(!!{})
发布于 2020-10-04 15:11:25
由于在React中设置状态的异步性质,调用状态的设置器(setCurrentUser)可能会出现问题。我还没有找到明确的答案,当我使用React时,它是异步的setState还是同步的。在我看来,在这种复杂的情况下,最好的解决方案就是使用类。它将为您提供许多使用钩子无法重现的生命周期方法,在auth组件中会更合适。React Hooks并不是在所有情况下都是类的替代品,它只是一个工具,它允许您在只需要进行简单改进的情况下不破坏现有代码。
https://stackoverflow.com/questions/64191896
复制相似问题