React localStorage destroys website when not logged in : learnprogramming

tl;dr let localFirstName = JSON.parse(user).firstName; does not work when user is not logged in or registered, because the value is null and therefore crashes my website completely. I have highlighted the most important parts with big text.

I have made a very simple website that shouldn’t require security or complex stuff, as this is just to learn react and other web technologies.

I need to create a functionality that can return the first name of the user who has logged in, and “anonymous” when not logged in.So far I have used the following inside two functions inside my login.js file to remember the user who either login or register:

Login() {... localStorage.setItem('user', JSON.stringify(userInfo.data.userInformation)); ...}

Register() {... localStorage.setItem('user', JSON.stringify(user)); ...}

The full code of login.js can be seen right below:

import { useState } from "react";
import { Link } from "react-router-dom";
import axios from "axios";

const baseURL = "http://127.0.0.1:3001/user";

export function Login() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  async function loginUser() {
    const user = {
      password: password,
      id: email,
    };
    try {
      let response = await axios.put(baseURL, user);
      let userInfo = await axios.get(baseURL + "/" + email);
      console.log(userInfo.data.userInformation.email);

      localStorage.setItem(
        "user",
        JSON.stringify(userInfo.data.userInformation)
      );

      alert("Successfully logged in");
      window.location.href = "/";
    } catch (err) {
      console.log(err);
      alert("Invalid email or password");
    }
  }
  return (
    <div className="col-sm-6 offset-sm-3">
      <h1>Login Page</h1>
      <input
        type="text"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        className="form-control"
        placeholder="Email"
      />
      <br />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        className="form-control"
        placeholder="Password"
      />
      <br />
      <button onClick={loginUser} className="btn btn-primary">
        Login
      </button>

      <br />
      <Link to="/register">
        <p>Register</p>
      </Link>
    </div>
  );
}

export function Register() {
  const [firstName, setFirstName] = useState("");
  const [familyName, setFamilyName] = useState("");
  const [password, setPassword] = useState("");
  const [email, setEmail] = useState("");

  async function signUp() {
    const user = {
      firstName: firstName,
      familyName: familyName,
      password: password,
      id: email,
    };
    let response = await axios.post(baseURL, user);
    if (response.status === 200) {
      window.location.href = "/";
    } else {
      alert("Email already exists");
    }
    response = await response;
    localStorage.setItem("user", JSON.stringify(user));
    console.log(localStorage.getItem("user"));
    window.location.href = "/";
  }
  return (
    <div className="col-sm-6 offset-sm-3">
      <h1>Register Page</h1>
      <input
        type="text"
        value={firstName}
        onChange={(e) => setFirstName(e.target.value)}
        className="form-control"
        placeholder="First Name"
      />
      <br />
      <input
        type="text"
        value={familyName}
        onChange={(e) => setFamilyName(e.target.value)}
        className="form-control"
        placeholder="Family Name"
      />
      <br />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        className="form-control"
        placeholder="Password"
      />
      <br />
      <input
        type="text"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        className="form-control"
        placeholder="Email"
      />
      <br />
      <button onClick={signUp} className="btn btn-primary">
        Sign Up
      </button>
    </div>
  );
}

Then I created a Menu() (a header) to display the username, and a submenu for either logging in or logging out (https://imgur.com/a/CqhSjgN)

I then created two functions inside that allows me to access the firstName, and also check if the user is logged in or not to change the submenu:

let user=localStorage.getItem('user');

let localFirstName = JSON.parse(user).firstName;<-- BIG PROBLEM WITH THIS FUNCTION

However, user returns null when a user is not logged in, and when I press login the login log in login.js returns undefined (console.log(userInfo.data.userInformation.email);) this can be seen here: https://imgur.com/a/CWIrvbS

Uncaught TypeError: Cannot read properties of null (reading 'firstName')
    at Menu (menu.js:17:1)

I use this inside the Menu() to create the different submenu (one for when you are logged in, and one when you are logged out).

{
  !user ? (
    <li>
      <a href="#">
        <span className="flaticon-user"></span>
      </a>
      <ul className="submenu">
        <li>
          <span>You are not logged in</span>
        </li>
        <li>
          <a className="btn" href="/login">
            Login
          </a>
        </li>
      </ul>
    </li>
  ) : (
    <li>
      <a href="#">
        <span className="flaticon-user"></span>
      </a>
      <ul className="submenu">
        <li>
          <span>You are logged in</span>
        </li>
        <li>
          <button onClick={logOut}>Logout</button>
        </li>
      </ul>
    </li>
  );
}

This does work both when the user is logged out and logged in thankfully.

However, the line <li>{localFirstName}</li> completely breaks the website, as seen before (TypeError… because of firstName is null).

My complete menu.js can be seen here:

import Nav from "react-bootstrap/Nav";
import Navbar from "react-bootstrap/Navbar";
import Container from "react-bootstrap/Container";
import { Outlet, Link } from "react-router-dom";
import "./css/bootstrap.min.css";
import "./css/owl.carousel.min.css";
import "./css/flaticon.css";
import "./css/bootstrap.min.css";
import "./css/slick.css";
import "./css/nice-select.css";
import "./css/fontawesome-all.min.css";
import "./css/style.css";
import "./css/slicknav.css";

export function Menu() {
  let user = localStorage.getItem("user");
  //let localFirstName = JSON.parse(user).firstName;
  console.log(user);
  //console.log(user.firstName);

  function logOut() {
    localStorage.removeItem("user");
    window.location.reload();
  }

  return (
    <>
      <header>
        <div className="header-area">
          <div className="main-header header-sticky">
            <div className="container-fluid">
              <div className="menu-wrapper">
                <div className="logo">
                  <a href="index.html">
                    <img src="assets/img/logo/logo.png" alt="" />
                  </a>
                </div>

                <div className="main-menu d-none d-lg-block">
                  <nav>
                    <ul id="navigation">
                      <li>
                        <Link to="/">Home</Link>
                      </li>
                      <li>
                        <Link to="/productlist">Products</Link>
                      </li>
                      <li>
                        <a href="about.html">about</a>
                      </li>
                      <li className="hot">
                        <a href="#">Latest</a>
                        <ul className="submenu">
                          <li></li>
                          <li>
                            <Link to="/main">Main</Link>
                          </li>
                        </ul>
                      </li>
                      <li>
                        <a href="blog.html">Categories</a>
                        <ul className="submenu">
                          <li>
                            <a href="blog.html">Drinks</a>
                          </li>
                          <li>
                            <a href="blog-details.html">Meals</a>
                          </li>
                          <li>
                            <a href="blog-details.html">Snacks</a>
                          </li>
                        </ul>
                      </li>
                      <li>
                        <a href="#">Pages</a>
                        <ul className="submenu">
                          <li>
                            <a href="login.html">Login</a>
                          </li>
                          <li>
                            <a href="cart.html">Cart</a>
                          </li>
                          <li>
                            <a href="elements.html">Element</a>
                          </li>
                          <li>
                            <a href="confirmation.html">Confirmation</a>
                          </li>
                          <li>
                            <a href="checkout.html">Product Checkout</a>
                          </li>
                        </ul>
                      </li>
                      <li>
                        <a href="contact.html">Contact</a>
                      </li>
                      <li>{localFirstName}</li>

                      {!user ? (
                        <li>
                          <a href="#">
                            <span className="flaticon-user"></span>
                          </a>
                          <ul className="submenu">
                            <li>
                              <span>You are not logged in</span>
                            </li>
                            <li>
                              <a className="btn" href="/login">
                                Login
                              </a>
                            </li>
                          </ul>
                        </li>
                      ) : (
                        <li>
                          <a href="#">
                            <span className="flaticon-user"></span>
                          </a>
                          <ul className="submenu">
                            <li>
                              <span>You are logged in</span>
                            </li>
                            <li>
                              <button onClick={logOut}>Logout</button>
                            </li>
                          </ul>
                        </li>
                      )}
                    </ul>
                  </nav>
                </div>
                <div className="header-right">
                  <ul>
                    <li>
                      <Link to="/cart">
                        <span className="flaticon-shopping-cart"></span>
                      </Link>
                    </li>
                  </ul>
                </div>
              </div>

              <div className="col-12">
                <div className="mobile_menu d-block d-lg-none"></div>
              </div>
            </div>
          </div>
        </div>
      </header>

      <Outlet />
    </>
  );
}

How do I fix this? I just want to be able to see the first name of the user who has logged in and be able to change the submenu when the user is not logged in and when the user is. I don’t need any fancy functions, so I wanted to just use localStorage somehow. It nearly works, but not when the user is logged in.

Leave a Comment