Search code examples
javascriptreactjsgetdom-eventsconstants

React UI not updating on return <Navigate to="/Login" />


I'm simply attempting to call a function submitformdata(data), which submits data to a database and returns a successRegister string on completion. Upon the return of this success string I want to navigate straight to the login page without further user interaction. What I have below runs without error, but it does not navigate to the \Login page even when the toLogin variable is set to successRegister verified by a console log statement. I expect it is something conceptual I am missing regarding how UI states are updated.

export default function Register() {

const [toLogin, setToLogin] = React.useState("failRegister");

const handleSubmit = (event) => {
    event.preventDefault();

    const data = new FormData(event.currentTarget);

    if (data.get('email') === '' || data.get('password') === '' || data.get('verifypassword') === '' || data.get('firstName') === '' || data.get('lastName') === '') {
        return
    }

    submitformdata(data).then(response => {

        setToLogin(response);

        if (toLogin === "successRegister") {
            return <Navigate to="/Login" />;
        }
    });
};

return (code here for the Register page);

Solution

  • There are a few things you must consider when using react hooks. First do I need to use a react hook or can I use a plain variable? If you can use a plain variable and you don't need persistence between renders, then use a variable.
    If you must have persistence between renders, then use a hook!
    The code you provided doesn't use the toLogin state hook at all, and doesn't require it to be persistent between renders! With the logic encountered above we can see that there is no real reason or need for this hook in this case. Check out the code below.

    import { useNavigate } from 'react-router-dom'; //using v6 here.
    

    ...

    //No hooks required for persistence between renders.
    //You can use a hook if you wish to handle errors and display them.
    const navigate = useNavigate();
    
    const handleSubmit = (event) => {
        event.preventDefault();
    
        const data = new FormData(event.currentTarget);
    
        if (data.get('email') === '' || data.get('password') === '' || data.get('verifypassword') === '' || data.get('firstName') === '' || data.get('lastName') === '') {
            return
        }
    
        submitformdata(data).then(response => {
    
            //In this case the response must be "successRegister"
    
            if (response === "successRegister") {
                //returning <Navigate to="/Login" /> doesn't work because it is the return of the onSubmit function.
                navigate("/Login");
                //No return needed for this function.
            }
        });
    };
    
    return (code here for the Register page);
    

    Further Details

    Lets explain why your code doesn't work as you anticipate. First, React hook state updates are asynchronous meaning they don't happen immediately! So when you setToLogin using your dispatch of the useState hook you haven't actually updated the toLogin "variable" or toLogin state. So all the if statement see's is the original "failRegister" value that it was initialized to.
    Second, you aren't returning a UI component to the ReactDOM you are returning a react component (JSX) to the onSubmit function (which doesn't render anything). Using the react-router-dom version 6 you can useNavigate hook to handle React Navigation between pages.

    The reason I chose the code above is because I don't find a reason to set a variable to the response object if all we are going to do is a quick if statement to compare the response with a string... So I just compared directly with no intermediate variable and left all the rest of your code the same (removing the unused hook and adding the new navigation hook). To make your register code more robust you could add an "else" block to your if statement that and add a hook that would handle errors and display them appropriately.

    Happy coding and learning.