简体   繁体   中英

can't perform a react state update on an unmounted component issue with useEffect

I'm trying to redirect my user to a private route. I'm using redux thunk to fetch user info from the database, with storeUser(), if the info exists then the user proceeds otherwise they get redirected back to the home page. However its not working as expected. Its redirecting back to the home page when It should be proceeding. I can do this using class based syntax and componentDidMount. I tried to counter this issue of no access to componentDidMount by using the authChecked state to determine when the component has finished rendering

const PrivateRoute = (props) => {
    const [authChecked, handleAuthChecked] = useState(false);
    const [isAuth, handleIsAuth] = useState(false);

    useEffect(() => {
        props
            .storeUser()
            .then(() => {
                props.user.email ? handleIsAuth(true) : handleIsAuth(false);
                handleAuthChecked(true);
            })
            .catch(() => {
                handleAuthChecked(true);
            });
    }, [props]);

    if (authChecked) {
        return isAuth ? <props.component /> : <Redirect to="/" />;
    }
    return null;
};

const mapStateToProps = (state) => {
    return {
        user: state.user,
    };
};

export default connect(mapStateToProps, { storeUser })(PrivateRoute);

The code will always redirect the user though. isAuth will never return true even though props.user.email is true. It runs and redirects before it has chance to run handleIsAuth(true)

You have 2 issues that may be causing the defects you see:

  1. First issue is caused by function scope within useEffect and your callback for storeUser . Instead of relying on the callback to determine whether the user has an email address, just do that in your render condition and let redux + react render cycle help you out.
  2. In addition, you should only call the storeUser action on mount. Not every time props updates.

For example:

const PrivateRoute = (props) => {
    const [authChecked, handleAuthChecked] = useState(false);

    useEffect(() => {
        props
            .storeUser()
            .then(() => {
                handleAuthChecked(true);
            })
            .catch(() => {
                handleAuthChecked(true);
            });
    }, []);

    if (authChecked) {
        return !!props.user.email 
          ? <props.component /> 
          : <Redirect to="/" />;
    }
    
    return null;
};

const mapStateToProps = (state) => {
    return {
        user: state.user,
    };
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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