Abhishek Kumar
Abhishek Kumar

Reputation: 9

LocalStorage is not working with React Context

I have tried to use useEffect to store user details in local storage but unable. Please do any help on it.

Full Code :


const AuthContext = createContext()

const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null); 

  useEffect(() =>{
    const storedUser = JSON.parse(localStorage.getItem('user'))
    setUser(storedUser)
  },[])

  const login = (userData) => {
    localStorage.setItem('user', JSON.stringify(userData));
    setUser(userData);
  };

  const getUser = () => {
    return JSON.parse(localStorage.getItem("user"))
  }

Upvotes: -1

Views: 90

Answers (3)

WeDoTheBest4You
WeDoTheBest4You

Reputation: 1954

The following sample code has used the same component of yours, and it found working with this version. Please use the code to check it with yours and find where does the context fail.

The intend of the sample code is just to show how context can be used along with localStorage. The code does not intend to provide a full implementation of login processes.

Notes on the codes, a full listig of code is given below.

a1. The Login component must be enclosed by AuthProvider as below.

<AuthProvider>
   <Login />
</AuthProvider>

a2. Inside AuthContext, the children it receives must be enclosed within the provider as below. Please take note that the values for the context is provided here.

<AuthContext.Provider value={{ login, getUser }}>
  {children}
</AuthContext.Provider>

b. useContext hook must be used prior to accessing the context object. The following code does the same.

function Login() {
  const authContext = useContext(AuthContext);
...

c. The function objects login and getUser have been referenced through the context object as below.

function handleAuthenticate(e) {
...
   authContext.login(user);
...


function Login() {
  ...
  const name = authContext.getUser()?.name;
  const password = authContext.getUser()?.password;
  ...

d. The getUser has been suitably modified as below,

const getUser = () => {
    // return JSON.parse(localStorage.getItem('user'));
    return user;
  };

app.js

import { useContext, createContext, useState, useEffect } from 'react';

const AuthContext = createContext();

export default function App() {
  return (
    <>
      <AuthProvider>
        <Login />
      </AuthProvider>
    </>
  );
}

function Login() {
  const authContext = useContext(AuthContext);

  const name = authContext.getUser()?.name;
  const password = authContext.getUser()?.password;

  const [feedback, setFeedback] = useState(name ? 'Welcome back 🥰' : '');

  function handleAuthenticate(e) {
    e.preventDefault();

    const form = e.target;
    const formData = new FormData(form);
    const user = Object.fromEntries(formData.entries());
    console.log(user);
    authContext.login(user);
    setFeedback('Logged in 😀');
  }

  return (
    <form method="post" onSubmit={handleAuthenticate}>
      <h3>{feedback}</h3>
      user name : <input name="name" defaultValue={name}></input>
      <br />
      Password : <input name="password" defaultValue={password}></input>
      <br />
      <button type="submit">Login</button>
    </form>
  );
}

const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);

  useEffect(() => {
    const storedUser = JSON.parse(localStorage.getItem('user'));
    setUser(storedUser);
  }, []);

  const login = (userData) => {
    localStorage.setItem('user', JSON.stringify(userData));
    setUser(userData);
  };

  const getUser = () => {
    // return JSON.parse(localStorage.getItem('user'));
    return user;
  };
  return (
    <AuthContext.Provider value={{ login, getUser }}>
      {children}
    </AuthContext.Provider>
  );
};

Test run

On loading the App.

enter image description here

Getting ready to login

enter image description here

After clicking Login button

enter image description here

After reloading the App.

enter image description here

Upvotes: -1

AcidSnake
AcidSnake

Reputation: 41

const AuthContext = createContext()

const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null); 

  useEffect(() =>{
    const storedUser = JSON.parse(localStorage.getItem(`${user}`))
    setUser(storedUser)
  },[])

  const login = (userData) => {
    localStorage.setItem(`${user}`, JSON.stringify(userData));
    setUser(userData);
  };

  const getUser = () => {
    return JSON.parse(localStorage.getItem(`${user}`))
  }

Are you trying to reference the variable? I think you need string interpolation for your "user". I changed it for you in the code above thinking it should work if you're trying to reach that variable. String interpolation is what I normally use when trying to put a variable inside a string using proper syntax ${varName} inside a ` (it's esc key on the keyboard also known as backticks or grave accents) quotation marks for this to work. It will not work with the other quotation marks, but only that one.

I hope this works.

Upvotes: -1

Sarkis
Sarkis

Reputation: 370

You're utilizing the useState hook within the useEffect without any dependencies. Something I noticed at first glance.

Secondly, js prop localStorage is not always rendered synchronously with the browser so sometimes it can be undefined

My suggestion is to add an if/else statement to perform local storage operations only when it's defined.

Side note: your question needs to be more descriptive.

const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null); 

  useEffect(() =>{
    const storedUser = JSON.parse(localStorage.getItem('user'))
    if (storedUser) {
       setUser(storedUser)
} else setUser("noLocalStorage")
  },[])

  const login = (userData) => {
    //if ... else 
      localStorage.setItem('user', JSON.stringify(userData));
    setUser(userData);
  };

  const getUser = () => {
    //if... else
    return JSON.parse(localStorage.getItem("user"))
  }

Upvotes: -1

Related Questions