0

I created logged in form wherein it will pop-out a toastify when logged in correctly. So my problem right now is I have a logic wherein the user can only access the website when his account is active, but my toastify is not popping correctly. I'm using reduxjs/toolkit my state.

So what I'm trying to achieve here:

1.) Show an error message if the account is not existing or wrong password

2.) Show Account still pending if the user correctly input his username and password but still not active

3.) Navigate to login page when account is active

api/login.js

const login = async (req,res, next) =>{
    try {
        const user = await User.findOne({studentNumber: req.body.studentNumber})
        if(!user) return next(createError(404, "User not found!"))

        const isPasswordCorrect = await bcrypt.compare(req.body.password, user.password)
        if(!isPasswordCorrect) return next(createError(400,"Wrong password or Username!"))

        const accessToken = jwt.sign({id: user._id, isAdmin: user.isAdmin},  'secretkey')

        const {password, ...others} = user._doc
        
        if(others.status === 'active'){
            res.status(200).json({...others, accessToken})
        }
        else{
         next(createError(203, "Account is still pending.."))
        }     

    } catch (error) {
        next(error);
    }
}

authSlice.js

const authSlice = createSlice({
name: 'auth',
initialState: {
    currentUser: null,
    isFetching : false,
    isError: false,
    isSuccess: false,
    message: ''
},
reducers: {
    resetState: (state) =>{
        state.currentUser = null;
        state.isFetching = false
        state.isError = false
        state.isSuccess = false

    },
    loginStart: (state)=>{
        state.isFetching = true;
        state.isError = false;
    },
    loginSuccess: (state, action) =>{
        state.isFetching = true;
        state.isSuccess = true;
        state.currentUser = action.payload
        state.message = action.payload

    },
    loginFailure: (state, action) =>{
        state.isSuccess = false;
        state.isFetching = false;
        state.isError = true;
        state.message = action.payload
    }, 
}

})

In authSlice.js, I have a problem that it automatically run the loginFailure, even though the user correctly input it's credential.

apiCall.js

const loginUser = async (user, dispatch) => {
  dispatch(loginStart());
  try {
    const res = await publicRequest.post("/auth/login", user);
    dispatch(loginSuccess(res.data));
  } catch (err) {
    dispatch(loginFailure());
  }
};

Login.jsx

  const {isError, currentUser, message} = useSelector((state) => state.auth)

  const dispatch = useDispatch()
  const navigate = useNavigate()


  const {register, handleSubmit, formState: {errors}} = useForm({
    studentNumber: '',
    password: ''
  })
  

  const onSubmit = ({studentNumber,password}) =>{
    let user ={studentNumber, password}
    loginUser(user,dispatch)
  }

  useEffect(() =>{
    if(isError){
      toast.error(message)
    }
    dispatch(resetState())
  },[dispatch, isError])

  useEffect(() =>{
    if(currentUser){
      toast.success(message)
    }
  },[dispatch, currentUser])

Login.jsx

const Login () =>{
const {isError, currentUser, message} = useSelector((state) => state.auth)

  const dispatch = useDispatch()
  const navigate = useNavigate()


  const {register, handleSubmit, formState: {errors}} = useForm({
    studentNumber: '',
    password: ''
  })
  

  const onSubmit = ({studentNumber,password}) =>{
    let user ={studentNumber, password}
    loginUser(user,dispatch)
  }

  useEffect(() =>{
    if(isError){
      toast.error(message)
    }
    dispatch(resetState())
  },[dispatch, isError])

  useEffect(() =>{
    if(currentUser){
      toast.success(message)
    }
  },[dispatch, currentUser])

   return (
   <form onSubmit={handleSubmit(onSubmit)}>
       <TextField name="studentNumber" {...register('studentNumber)} type="text" />
       <TextField name="password" {...register('password)} type="password" />
    </form>

)
}

EDIT Please ignore the form field if I type it wrong, I just copy paste it and missed something

Zurcemozz
  • 183
  • 1
  • 9
  • The `{...register('studentNumber)}` and `{...register('password)}` expressions are not properly formatted. They should be wrapped in curly braces – Mithat Ercan Dec 23 '22 at 08:26

1 Answers1

0

In apiCall.js, don't just do dispatch(loginFailure());, instead inspect the response and if it has the 203 status code, dispatch the action differently. Maybe login failure, but with a payload that signals to your reducer that the user has logged in successfully, but their account is not active yet.

You probably also want to add another boolean flag to your state, something like state.auth.isActive, that is only true if the user account is not pending anymore. Or alternatively, if state.auth.currentUser is an object with more info, maybe the active/pending flag is contained in there already (in this case don't duplicate it).

timotgl
  • 2,865
  • 1
  • 9
  • 19