Home > Software design >  Why I am not getting the updated value from react redux state
Why I am not getting the updated value from react redux state

Time:08-14

I am a beginner and I am learning react js. I made a crud app for practice. I am implementing firebase to this app for authentication. But the problem is that I am not getting the updated value.

Index.jsx

Here in line no 11, I am not getting the latest user value.

import React, { useEffect } from 'react';
import { useSelector } from 'react-redux';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import ShowBooks from '../pages/ShowBooks';
import AddBook from '../pages/AddBook';
import EditBook from '../pages/EditBook';
import Login from '../pages/Login';
import Navbar from '../components/Navbar';

const Index = () => {
  const { user } = useSelector(state => state.case);
  let routes;
  if (user === null || user === undefined) {
    routes = (
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route path="*" element={<Navigate to="/login" replace={true} />} />
      </Routes>
    );
  } else {
    routes = (
      <>
        <Navbar />
        <Routes>
          <Route path="/" element={<ShowBooks />} />
          <Route path="/show-books" element={<ShowBooks />} />
          <Route path="/add-book" element={<AddBook />} />
          <Route path="/edit-book" element={<EditBook />} />
          <Route path="/login" element={<Login />} />
          <Route path="*" element={<Navigate to="/" replace={true} />} />
        </Routes>
      </>
    );
  }

  return <BrowserRouter>{routes}</BrowserRouter>;
};

export default Index;

Here is the code of BooksSlice.jsx:

import { createSlice } from '@reduxjs/toolkit';
import { v4 as uuidv4 } from 'uuid';

const initialBooks = {
  books: [
    {
      id: uuidv4(),
      title: 'Ordinary Differential Equation',
      author: 'Prof. Md. Abu Yousuf',
    },
    { id: uuidv4(), title: 'CSE Kit', author: 'Gyan Bitan' },
  ],
  user: JSON.parse(localStorage.getItem('user')) || null,
};

export const BooksSlice = createSlice({
  name: 'books',
  initialState: initialBooks,
  reducers: {
    showBooks: state => state,
    addBook: (state, action) => {
      state.books.push(action.payload);
    },
    deleteBook: (state, action) => {
      const id = action.payload;
      state.books = state.books.filter(book => book.id !== id);
    },
    updateBook: (state, action) => {
      const { id, title, author } = action.payload;
      const isBookExist = state.books.filter(book => book.id === id);
      if (isBookExist) {
        isBookExist[0].title = title;
        isBookExist[0].author = author;
      }
    },
  },
});

export const { showBooks, addBook, deleteBook, updateBook } =
  BooksSlice.actions;
export default BooksSlice.reducer;

Here is the code of store.js

import { configureStore } from '@reduxjs/toolkit';
import booksReducer from './BooksSlice';

const store = configureStore({
  reducer: {
    case: booksReducer,
  },
});

export default store;

And here is Login.jsx code:

import React, { useState } from 'react';
import { signInWithEmailAndPassword } from 'firebase/auth';
import { auth } from '../firebase/firebase';
import { useNavigate } from 'react-router-dom';

const Login = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState(false);

  const navigate = useNavigate();

  // Login Handler Function
  const loginHandler = event => {
    event.preventDefault();

    signInWithEmailAndPassword(auth, email, password)
      .then(userCredential => {
        // Signed in
        const user = userCredential.user;
        localStorage.setItem('user', JSON.stringify(user));
        navigate('/show-books', { replace: true });
      })
      .catch(error => {
        // const errorCode = error.code;
        // const errorMessage = error.message;
        setError(true);
      });
  };

  return (
    <div className="container pt-5">
      {error && (
        <p className="text-danger text-center">Wrong email or password!</p>
      )}
      <form className="w-75 mx-auto" onSubmit={loginHandler}>
        <div className="form-floating mb-3">
          <input
            type="email"
            className="form-control"
            placeholder="Email"
            value={email}
            onChange={event => setEmail(event.target.value)}
            required
          />
          <label>Email</label>
        </div>
        <div className="form-floating my-3">
          <input
            type="password"
            className="form-control"
            placeholder="Password"
            value={password}
            onChange={event => setPassword(event.target.value)}
            required
          />
          <label>Password</label>
        </div>
        <button type="submit" className="btn btn-dark btn-lg text-light">
          Log In
        </button>
      </form>
    </div>
  );
};

export default Login;

How can I get the updated user value on Index.jsx?

CodePudding user response:

You need to create a "login" action and dispatch the authenticated user object to the store when a user authenticates.

Example:

export const BooksSlice = createSlice({
  name: 'books',
  initialState: initialBooks,
  reducers: {
    ...
    login: (state, action) => {
      state.user = action.payload;
      localStorage.setItem('user', JSON.stringify(action.payload));
    },
  },
});

export const {
  showBooks,
  addBook,
  deleteBook,
  updateBook,
  login,
} = BooksSlice.actions;
export default BooksSlice.reducer;

...

import React, { useState } from 'react';
import { signInWithEmailAndPassword } from 'firebase/auth';
import { useDispatch } from 'react-redux';
import { auth } from '../firebase/firebase';
import { useNavigate } from 'react-router-dom';
import { login } from '../path/to/BooksSlice';

const Login = () => {
  ...

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

  // Login Handler Function
  const loginHandler = event => {
    event.preventDefault();

    signInWithEmailAndPassword(auth, email, password)
      .then(userCredential => {
        // Signed in
        const user = userCredential.user;
        dispatch(login(user)); // <-- dispatch user object to store
        navigate('/show-books', { replace: true });
      })
      .catch(error => {
        // const errorCode = error.code;
        // const errorMessage = error.message;
        setError(true);
      });
  };

  return (
    ...
  );
};
  • Related