如何在useEffect中更新状态的条件组件中有条件地渲染?

时间:2020-11-10 00:16:20

标签: reactjs react-hooks

在react中,我有一个私有路由组件,该组件具有一个isAuthenticated状态值,该状态值用于呈现正在包装的组件,或重定向回我的登录页面。

为了检测刷新并执行身份验证检查,我添加了一个useEffect钩子,希望可以检查身份验证状态,然后更新isAuthenticated,然后返回组件或重定向

const PrivateRoute: React.FC<IPrivateRouteProps> = (props) => {
    const dispatch = useDispatch();
    const [isAuthenticated, setIsAuthenticated] = React.useState(false);

    useEffect(() => {
        authService.getIdentity().then(response => {
            if (response) {
                dispatch(signIn(new Identity(response.account)));
                setIsAuthenticated(true);
            } else {
                setIsAuthenticated(false);
            }         
        });
    }, [])

    return isAuthenticated ? (
        <Route {...props} component={props.component} render={undefined} />
    ) : (
        <Redirect to={{ pathname: props.redirectPath }} />
    );
};

不幸的是,这不起作用,我不确定为什么或如何解决它。

isAuthenticated的值在渲染时始终为false,并且在控制台中出现以下错误...。

index.js:1 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
    in PrivateRoute (at App.tsx:23)

我可以确认它确实流向setIsAuthenticated(true),但是在渲染之前,这从未反映在isAuthenticated的值中。

我如何/应该解决这个问题?

谢谢

2 个答案:

答案 0 :(得分:1)

我认为问题在于代码第一次运行时,它使用isAuthenticated false评估渲染,然后使用useEffect并尝试更新值,但是您已经被重定向到另一个页面。

我建议使用另一个变量来了解身份验证是否已通过,并且仅在身份验证完成后才能继续。

const PrivateRoute: React.FC<IPrivateRouteProps> = (props) => {
    const dispatch = useDispatch();
    const [loading, setLoading] = React.useState(true);
    const [isAuthenticated, setIsAuthenticated] = React.useState(false);

    useEffect(() => {
        authService.getIdentity().then(response => {
            if (response) {
                dispatch(signIn(new Identity(response.account)));
                setIsAuthenticated(true);
            } else {
                setIsAuthenticated(false);
            }
            setLoading(false);         
        });
    }, [])

    if (isLoading) {
        //we are not ready yet
       return null;
    }

    return isAuthenticated ? (
        <Route {...props} component={props.component} render={undefined} />
    ) : (
        <Redirect to={{ pathname: props.redirectPath }} />
    );
};

答案 1 :(得分:0)

如您所见,它显示为Can't perform a React state update on an unmounted component.。 为防止出现此问题,您能否尝试像这样将<Route><Redirect>放在<React.Fragment>内?

return isAuthenticated ? (
    <React.Fragment>
        <Route {...props} component={props.component} render={undefined} />
    </React.Fragment>
) : (
    <React.Fragment>
        <Redirect to={{ pathname: props.redirectPath }} />
    </React.Fragment>
);