skip to Main Content

I am trying to redirect user after successful login. I did it this way but it does not work. How can I fix this issue or how can I do it correctly?

main.jsx

enter image description here

Login.jsx

imports ...

function Login() {
    const [login, setLogin] = useState('');
    const [password, setPassword] = useState('');
    const [loginClass, setLoginClass] = useState('');
    const [passwordClass, setPasswordClass] = useState('');

    const [isLoggedIn, setIsLoggedIn] = useState(false);

    const submit = async (evt) => {
        evt.preventDefault();
        console.log(login, password);
        if (login.length === 0 || password.length === 0) {
            console.log('stop')
            if (!login) { 
                setLoginClass('is-invalid'); 
            }

            if (!password) { 
                setPasswordClass('is-invalid');
            }
        } else {
            console.log('req')
            await axios
                .post('http://localhost:5000/test/auth/login', {
                    login: login,
                    password: password
                })
                .then((response) => {
                    console.log(response);
                    const { data } = response;
                    if (data.status == 200) {
                        console.log('entered successfully');
                        setIsLoggedIn(true);
                    } else {
                        console.log('could not enter');
                    }
                })
                .catch((error) => {
                    console.log(error);
                });

            setPassword('');
            setLogin('');
            setLoginClass('');
            setPasswordClass('');
        }
        if (isLoggedIn) {
            return <Navigate to="/main" replace={true}/>
        }
        return
    };

    return (
        <div className="container col-xl-10 col-xxl-8 px-4 py-5">
            ...
                            <input
                                type="text"
                                className={`form-control ${loginClass}`}
                                id="login"
                                placeholder="Login"
                                value={login}
                                onChange={(evt) => { setLogin(evt.target.value) }}
                            />
                            ...
                            <input
                                type="password"
                                className={`form-control ${passwordClass}`}
                                id="password"
                                placeholder="Password"
                                value={password}
                                onChange={(evt) => { setPassword(evt.target.value) }}
                            />
                        <button className="w-100 btn btn-lg btn-primary" onClick={submit}>Enter</button>
                    </form>
                </div>
            </div>
        </div>
    );
}

export default Login;

2

Answers


  1. One of the ways to achieve navigation in your React application is to use the useNavigate hook from react-router-dom

    import { useNavigate } from 'react-router-dom';
    
    const navigate = useNavigate();
    

    Modify this condition in your submit function

      if (data.status == 200) {
        console.log("entered successfully");
        navigate("/main");
        setIsLoggedIn(true);
      } else {
        console.log("could not enter");
      }
    
    
    Login or Signup to reply.
  2. Issues

    • Attempting to return JSX from an asynchronous callback function.

      The code is attempting to issue a redirect from within the submit handler. You can’t return JSX from a callback and expect it to be rendered to the DOM and have any effect. Navigate would need to be returned from the Login as part of the regular JSX it renders.

    • Attempting to access a stale closure over state.

      submit enqueues some state updates and the code incorrectly attempts to access the isLoggedIn state to effect a redirect action.

    • It is generally considered a Javascript anti-pattern to mix async/await with Promise chains. Pick one pattern or the other.

    const submit = async (evt) => {
      evt.preventDefault();
      console.log(login, password);
      if (login.length === 0 || password.length === 0) {
        console.log('stop')
        if (!login) { 
          setLoginClass('is-invalid'); 
        }
    
        if (!password) { 
          setPasswordClass('is-invalid');
        }
      } else {
        console.log('req')
        await axios
          .post('http://localhost:5000/test/auth/login', {
            login: login,
            password: password
          })
          .then((response) => {
            console.log(response);
            const { data } = response;
            if (data.status == 200) {
              console.log('entered successfully');
              setIsLoggedIn(true);
            } else {
              console.log('could not enter');
            }
          })
          .catch((error) => {
            console.log(error);
          });
    
        setPassword('');
        setLogin('');
        setLoginClass('');
        setPasswordClass('');
      }
    
      if (isLoggedIn) { // <-- won't have value from any state enqueued updates above
        return <Navigate to="/main" replace={true} />; // <-- can't do this
      }
      return
    };
    

    Solutions

    1. Enqueue the isLoggedIn state update as you are and return the Navigate component with the regular JSX to issue a declarative redirect.

      function Login() {
        const [login, setLogin] = useState('');
        const [password, setPassword] = useState('');
        const [loginClass, setLoginClass] = useState('');
        const [passwordClass, setPasswordClass] = useState('');
      
        const [isLoggedIn, setIsLoggedIn] = useState(false);
      
        const submit = async (evt) => {
          evt.preventDefault();
      
          if (!login.length || !password.length) {
            if (!login) { 
              setLoginClass('is-invalid'); 
            }
      
            if (!password) { 
              setPasswordClass('is-invalid');
            }
          } else {
            try {
              const { data } = await axios.post(
                'http://localhost:5000/test/auth/login',
                { login, password }
              )
      
              if (data.status == 200) {
                setIsLoggedIn(true);
              } else {
                console.log('could not enter');
              }
            } catch(error) {
              console.log(error);
            };
      
            setPassword('');
            setLogin('');
            setLoginClass('');
            setPasswordClass('');
          }
        };
      
        // Return JSX from function component
        if (isLoggedIn) {
          return <Navigate to="/main" replace />; // <-- declarative redirect
        }
      
        return (
          ...
        );
      }
      
    2. Use the useNavigate hook and issue an imperative redirect from the submit handler.

      import { useNavigate } from 'react-router-dom';
      ...
      
      function Login() {
        const navigate = useNavigate();
      
        const [login, setLogin] = useState('');
        const [password, setPassword] = useState('');
        const [loginClass, setLoginClass] = useState('');
        const [passwordClass, setPasswordClass] = useState('');
      
        const submit = async (evt) => {
          evt.preventDefault();
      
          if (!login.length || !password.length) {
            if (!login) { 
              setLoginClass('is-invalid'); 
            }
      
            if (!password) { 
              setPasswordClass('is-invalid');
            }
          } else {
            try {
              const { data } = await axios.post(
                'http://localhost:5000/test/auth/login',
                { login, password }
              )
      
              if (data.status == 200) {
                navigate("/main", { replace: true }); // <-- imperative redirect
              } else {
                console.log('could not enter');
              }
            } catch(error) {
              console.log(error);
            };
      
            setPassword('');
            setLogin('');
            setLoginClass('');
            setPasswordClass('');
          }
        };
      
        return (
          ...
        );
      }
      
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search