Search code examples
javascriptreactjsredux

display alert errors when form is submitted


I'm trying to display alert if the user submit bad email and password, but I'm struggling with this. the errors and load states are updated when dispatch (login(user)) is executed. but When the user click on login to submit the form the errors and loading aren't checked and directly navigate to the home page ('/').

this is my login screen code :

import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Alert, Button, Form, Spinner } from "react-bootstrap";
import { useNavigate } from "react-router-dom";
import { login } from "../JS/Action/user";



const Login = () => {
const [User, setUser] = useState({});
const errors = useSelector((state) => state.userReducer.errors);
const loading = useSelector((state) => state.userReducer.loadUser);
const dispatch = useDispatch();
const navigate = useNavigate();


const handleChnage = (e) => {
setUser({ ...User, [e.target.name]: e.target.value });
};
const handleUser = (e) => {
e.preventDefault();
dispatch(login(User))
navigate('/')

};
return (
 <div

>
  {errors && errors.map(el=><Alert variant="danger">{el.msg}</Alert>)}
  {loading && <Spinner animation="border" variant="secondary" />}

 <Form >
 
  
    <Form.Label>Email address</Form.Label>
    <Form.Control type="email" placeholder="Enter email" name="email" onChange={handleChnage} />

    <Form.Label>Password</Form.Label>
    <Form.Control type="text" placeholder="Password" name="password" onChange={handleChnage} />

    <Button variant="primary" type="submit" disabled={loading} onClick={handleUser} >
      login
    </Button>
  </Form>
</div>
);
};

export default Login;

this is the login Action :

//LOGIN USER
   export const login = (user) => async (dispatch) => {
  dispatch({ type: LOAD_USER });
  try {
    let result = await axios.post("/api/user/login", user);
    dispatch({ type: LOGIN_USER, payload: result.data });
    
  } catch (error) {
    dispatch({ type: FAIL_USER, payload: error.response.data.errors });
  }
  };

and this is the user reducer :

  //import

import {
  CLEAR_ERRORS,
  CURRENT_USER,
  FAIL_USER,
  LOAD_USER,
  LOGIN_USER,
  LOGOUT_USER,
  REGISTER_USER,
} from "../ActionTypes/user";

//initial state
const initialState = {
  user: null,
  loadUser: false,
  errors: null,
  isAuth: false,
  isAdmin: false
};

//pure function
const userReducer = (state = initialState, { type, payload }) => {
  switch (type) {
    case LOAD_USER:
      return { ...state, loadUser: true };
    case REGISTER_USER:
      localStorage.setItem("token", payload.token);
      return {
        ...state,
        user: payload.user,
        loadUser: false,
        isAuth: true,
        isAdmin: payload.user.isAdmin,
      };
    case LOGIN_USER:
      localStorage.setItem("token", payload.token);
      return {
        ...state,
        loadUser: false,
        isAuth: true,
        user: payload.user,
        isAdmin: payload.user.isAdmin,
      };
    case CURRENT_USER:
      return {
        ...state,
        loadUser: false,
        isAuth: true,
        user: payload,
        isAdmin: payload.isAdmin,
      };
    case LOGOUT_USER:
      localStorage.removeItem("token");
      return {
        user: null,
        loadUser: false,
        errors: null,
        isAuth: false,
        isAdmin: false
      };
    case FAIL_USER:
      return { ...state, errors:payload, loadUser: false };
    case CLEAR_ERRORS:
      return { ...state, errors:null };
    default:
      return state;
  }
};

//export
export default userReducer;

sorry for my bad englih guys hope you got the idea and you can help me..


Solution

  • You don't have to use navigate("/") in the handleUser function as it will not check whether the user is logged in or not but will navigate.

    const handleUser = (e) => {
        e.preventDefault();
        dispatch(login(User))
        // navigate('/')
    };
    

    Instead, use useEffect hook to check whether the user is logged in or not and alert and navigate.

    const user = useSelector((state) => state.userReducer.user);
    const error = useSelector((state) => state.userReducer.errors);
    
    useEffect(()=>{
        if(user){
            alert("Logged in successfully")
            navigate("/")
       }
    
        if(error){
            alert(error)
       }
    
    },[navigate,user,error])
    

    Hope it helps, Thanks.