简体   繁体   English

如何在useEffect中更新状态的react组件中有条件地呈现?

[英]How to conditionally render in a react component with state updated in useEffect?

In react I have a private route component that has an isAuthenticated state value that is used to either render the component it is wrapping, or redirect back to my login page.在 React 中,我有一个私有路由组件,它有一个isAuthenticated状态值,用于渲染它正在包装的组件,或者重定向回我的登录页面。

In order to detect a refresh and perform an authentication check, I added a useEffect hook in the hope that I could check the authentication status, then update isAuthenticated , then either return the component or redirect accordingly.为了检测刷新并执行身份验证检查,我添加了一个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 }} />
    );
};

Unfortunately this doesn't work and I'm not sure why or how to solve it.不幸的是,这不起作用,我不确定为什么或如何解决它。

The value of isAuthenticated is always false at the point of rendering and I get the following error in the console.... 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)

I can confirm that it does flow through to setIsAuthenticated(true) but this is never reflected in the value of isAuthenticated before rendering.我可以确认它确实流向setIsAuthenticated(true)但这在呈现之前从未反映在isAuthenticated的值中。

How can/should I solve this?我可以/应该如何解决这个问题?

Thanks,谢谢,

I think the issue is that the first time that the code run, it evaluates the render with isAuthenticated false, then the useEffect kicks in and tries to update the value but you have been already redirected to another page.我认为问题在于代码第一次运行时,它使用 isAuthenticated false 评估渲染,然后 useEffect 启动并尝试更新值,但您已经被重定向到另一个页面。

I will suggest to use another variable to know if the authentication has been validated, and only continue after the authentication has been done.我会建议使用另一个变量来了解身份验证是否已通过验证,并且仅在身份验证完成后继续。

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

As you can see it says Can't perform a React state update on an unmounted component.如您所见,它说Can't perform a React state update on an unmounted component. . . To prevent this issue, can you plz try to put <Route> and <Redirect> inside of <React.Fragment> like this?为了防止这个问题,你能试着把<Route><Redirect> <React.Fragment>像这样放在<React.Fragment>里面吗?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM