I have a problem in my MERN authentication system with redux-toolkit

Viewed 43

I am trying to create authentication system with redux toolkit everything looks ok but when I do conditional rendering it is not working properly at the start current User is null as initial state but till it renders different component which should render only if there is a current user

Below is my code

  1. auth Slice

import { createSlice } from "@reduxjs/toolkit";

// Get currentUser from localstorage

// const currentUser = JSON.parse(localStorage.getItem('currentUser'));
// currentUser ? currentUser :

const authSlice = createSlice({
  name: "auth", // Global state
  initialState: {
    currentUser: null,
    isFetching: false,
    error: false,
  },
  reducers: {
    // All the reducer

    // Reset To initial state

    reset: (state) => {
      state.currentUser = null;
      state.isFetching = false;
      state.error = false;
    },

    // Login Reducers
    loginStart: (state) => {
      state.isFetching = true;
    },
    loginSuccess: (state, action) => {
      state.isFetching = false;
      state.currentUser = action.payload;
    },
    loginFail: (state) => {
      state.isFetching = false;
      state.error = true;
    },

    // Register Reducers
    registerStart: (state) => {
      state.isFetching = true;
    },
    registerSuccess: (state, action) => {
      state.isFetching = false;
      state.currentUser = action.payload;
    },
    registerFail: (state) => {
      state.isFetching = false;
      state.error = true;
    },

    // Logout
    logoutSuccess: (state) => {
      (state.currentUser = null),
        (state.isFetching = false),
        (state.error = false);
    },
  },
});

export const {
  reset,
  loginStart,
  loginSuccess,
  loginFail,
  registerStart,
  registerSuccess,
  registerFail,
} = authSlice.actions;
export default authSlice.reducer;

  1. store

import { configureStore } from "@reduxjs/toolkit";
import authReducer from './authRedux'
import storage from 'redux-persist/lib/storage'
import { 
    persistReducer,
    persistStore,
    FLUSH,
    REHYDRATE,
    REGISTER,
    PURGE,
    PERSIST } from 'redux-persist';

const persistConfig={
    key:'root',
    version: 1,
    storage,
}

const persistedReducer = persistReducer(persistConfig, authReducer);

export const store = configureStore({
    reducer:{
        auth: persistedReducer,
    },
    middleware:(getDefaultMiddleware) =>
    getDefaultMiddleware({
        serializableCheck:{
            ignoreActions:[FLUSH,REGISTER,REHYDRATE,PERSIST,PURGE],
        },
    })
});

export let persistor = persistStore(store);

  1. Login

import React, { useState } from "react";
import { Form, Card, Button, Alert } from "react-bootstrap";
import { Link, useNavigate } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { login } from "../../Redux/apiCalls";
import UpdateProfile from "../UpdateProfile/Updateprofile";

export default function Login() {
  const [username, setUserName] = useState("");
  const [password, setPassword] = useState("");
  const dispatch = useDispatch();
  const currentUser = useSelector((state) => state.auth);
  const { isFetching, error } = useSelector((state) => state.auth);
  const navigate = useNavigate();

  async function handleSubmit(e) {
    e.preventDefault();
    try {
      if(!currentUser){
        navigate('/')
      }else{
        login(dispatch, { username, password });
        navigate('/');
      }
    } catch (error) {
      console.log(error);
    }
  }

  console.log(currentUser);
  return (
    <>
    {currentUser ? (<UpdateProfile/>):(
      <Card className="shadow-lg p-3 mb-2 bg-white rounded">
      <Card.Body>
        <h2 className="text-center mb-4">Log In</h2>
        {error && <Alert variant="danger">{error}</Alert>}
        <Form onSubmit={handleSubmit}>
          <Form.Group id="username">
            <Form.Label>UserName</Form.Label>
            <Form.Control
              type="text"
              required
              onChange={(e) => setUserName(e.target.value)}
            />
          </Form.Group>
          <Form.Group id="password">
            <Form.Label>Password</Form.Label>
            <Form.Control
              type="password"
              required
              onChange={(e) => setPassword(e.target.value)}
            />
          </Form.Group>
          <Button
            disabled={isFetching}
            className="w-100 mt-4 mb-4"
            type="submit"
          >
            Log In
          </Button>
        </Form>
        <div className="w-100 text-center mt-2">
          <Link to="/forgot-password">Forgot Password</Link>
        </div>
        <div className="w-100 text-center mt-3">
          Need an Account? <Link to="/signup">Sing Up</Link>
        </div>
      </Card.Body>
    </Card>
    )}
      
    </>
  );
}

As in login component at start it should render login page because there is no user but it renders update profile even in my redux dev tool it shows current user as null

2 Answers

From a quick look over I would check the following in Login:

async function handleSubmit(e) {
    e.preventDefault();
    try {
        if(!currentUser){
        navigate('/')
    } else {
        login(dispatch, { username, password });
        navigate('/');
    }
       } catch (error) {
           console.log(error);
       }
    }

I think your dispatch function should maybe look something like:

dispatch(login({ username, password }));

This is assuming that your login function accepts an object and wants to be passed username and password. I am unfamiliar with redux-persist, so apologies if I have missed something specific to that package.

I solved it I just make changes in use selector destructuring method

from this

const currentUser = useSelector((state) => state.auth);

To this

const currentUser = useSelector((state) => state.auth.currentUser);

Related