Search code examples
javascriptreactjsfirebasereduxlocal-storage

Why I am getting undefined from the localStorage?


I am trying to learn firebase by reading their documentation. I have added login using google account and email password. When I click on log in, I am dispatching setLogInValue and the state is updating but getting the value of isLoggedIn: undefined. But when I first visit the page the value of isLoggedIn is null. I expect the value of isLoggedIn: true after clicking on log in and redirect to homepage but as I am getting undefined the routing is not working.

slice.js

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

const initialState = {
  email: localStorage.getItem('email'),
  isLoggedIn: localStorage.getItem('loggedInStatus'),
};

export const slice = createSlice({
  name: 'slice',
  initialState,
  reducers: {
    setLogInValue: (state, action) => {
      state.email = localStorage.setItem('email', action.payload);
      state.isLoggedIn = localStorage.setItem('loggedInStatus', true);
    },
  },
});

export const { setLogInValue } = slice.actions;

export default slice.reducer;

Login.jsx

import React, { useState } from 'react';
import {
  getAuth,
  signInWithPopup,
  signInWithEmailAndPassword,
  GoogleAuthProvider,
} from 'firebase/auth';
import { useDispatch } from 'react-redux';
import { setLogInValue } from '../redux/slice';
import { useNavigate } from 'react-router-dom';
import { auth } from '../firebase/firebase';

const Login = () => {
  const [input, setInput] = useState({ email: '', password: '' });

  const inputHandler = event => {
    setInput({ ...input, [event.target.name]: event.target.value });
  };

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

  // const auth = getAuth();
  const googleSignIn = () => {
    const provider = new GoogleAuthProvider();
    signInWithPopup(auth, provider)
      .then(result => {
        const credential = GoogleAuthProvider.credentialFromResult(result);
        const token = credential.accessToken;
        // The signed-in user info.
        const user = result.user;
        dispatch(setLogInValue(user.email));
        // localStorage.setItem('loggedInStatus', true);
        navigate('/', { replace: true });
      })
      .catch(error => {
        // Handle Errors here.
        const errorCode = error.code;
        const errorMessage = error.message;
        // The email of the user's account used.
        const email = error.customData.email;
        // The AuthCredential type that was used.
        const credential = GoogleAuthProvider.credentialFromError(error);
        // ...
        console.log(errorMessage);
      });
  };

  const submitHandler = event => {
    event.preventDefault();

    // const auth = getAuth();
    signInWithEmailAndPassword(auth, input.email, input.password)
      .then(userCredential => {
        // Signed in
        const user = userCredential.user;
        console.log(user);
        dispatch(setLogInValue(input.email));

        setInput({
          email: '',
          password: '',
        });

        navigate('/', { replace: true });
      })
      .catch(error => {
        const errorCode = error.code;
        const errorMessage = error.message;
        console.log(errorMessage);
      });
  };

  return (
    <div className="container">
      <form
        className="w-75 mx-auto mt-5"
        onSubmit={event => submitHandler(event)}>
        <div className="form-floating mb-3">
          <input
            name="email"
            type="email"
            className="form-control"
            placeholder="[email protected]"
            value={input.email}
            onChange={inputHandler}
          />
          <label>Email address</label>
        </div>
        <div className="form-floating">
          <input
            name="password"
            type="password"
            className="form-control"
            placeholder="Password"
            value={input.password}
            onChange={inputHandler}
          />
          <label>Password</label>
        </div>
        <button
          type="submit"
          className="btn btn-primary btn-lg d-block mx-auto mt-3">
          Log in
        </button>
      </form>
      <button
        className="btn btn-primary btn-lg d-block mx-auto mt-3"
        onClick={googleSignIn}>
        Log in With Google
      </button>
    </div>
  );
};

export default Login;

Home.jsx

import React from 'react';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/js/bootstrap.min.js';
import 'bootstrap-icons/font/bootstrap-icons.css';
import { Routes, Route, Navigate } from 'react-router-dom';
import Nav from './components/Nav';
import Home from './pages/Home';
import Login from './pages/Login';
import { useSelector } from 'react-redux';

const App = () => {
  const { isLoggedIn } = useSelector(state => state.info);
  console.log('App:', isLoggedIn);

  let routes;
  if (isLoggedIn) {
    routes = (
      <>
        <Nav />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="*" element={<Navigate to="/" replace />} />
        </Routes>
      </>
    );
  } else {
    routes = (
      <>
        <Routes>
          <Route path="/login" element={<Login />} />
          <Route path="*" element={<Navigate to="/login" replace />} />
        </Routes>
      </>
    );
  }

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

export default App;

Nav.jsx

import React from 'react';
import { Link } from 'react-router-dom';

const Nav = () => {
  return (
    <nav className="navbar navbar-expand-lg bg-light ">
      <div className="container">
        <Link className="navbar-brand" to="/">
          Navbar
        </Link>
        <Link className="nav-link" to="/">
          Home
        </Link>
      </div>
    </nav>
  );
};

export default Nav;

Why I am getting undefined instead of "true/false/" of isLoggedIn value from the localStorage? How can I fix that?


Solution

  • The problem is in the code in 'slice.js':

    setLogInValue: (state, action) => {
      state.email = localStorage.setItem('email', action.payload);
      state.isLoggedIn = localStorage.setItem('loggedInStatus', true); // <<<< Problem here: function localStorage.setItem return 'undefined' value
    },
    

    so you should fix like this:

    setLogInValue: (state, action) => {
      localStorage.setItem('loggedInStatus', true)
      localStorage.setItem('email', action.payload);
    
      state.email = action.payload;
      state.isLoggedIn = true;
    },