简体   繁体   中英

Local storage not updating React

I'm btrying to save an array of objects in local storage, each time a user clicks a button, i add the username and email fron input fields but it keeps updating the local storage instead of appending new object to the array

Below is my code

const app = () => {
const [allusers,setAllusers] = useState([JSON.parse(localStorage.getItem('users')) || '']);
const [id,setId] = useState(0);
const [newuser,setNewuser] = useState({
    'id':id
    'name':'David',
    'email':'david@gmail.com'
})
const handleChange = () =>{
    setNewuser({...newuser,[e.target.name] : e.target.value});
}
  const add = ()=>{
      setAllusers([newuser])
      localStorage.setItem('users',JSON.stringify(allusers))
      setID(id+1); // increase id by 1
  }
  return(

      <div>
        <form>
        <input type="text" name="user" onChange={handleChange}>
        <input type="text" name="email" onChange={handleChange}>
        <button onclick={()=>save}>Save</button>
        </form>
      </div>
  )
}

export default app;

There were a lot of syntactical errors and use of functions like save which was never declared and still used.

I rewrote the whole example and made it a bit modular so that you can comprehend it better.

Here is the working example:

Final Output:

在此处输入图像描述

Full Source code:


import React, { useState, useEffect } from "react";
import "./style.css";
const App = () => {
  const [allusers, setAllusers] = useState([]);
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");

  const handleName = e => {
    setName(e.target.value);
  };

  const handleEmail = e => {
    setEmail(e.target.value);
  };
  const save = e => {
    e.preventDefault();
    let newUsers = {
      id: Math.floor(Math.random() * 100000),
      name: name,
      email: email
    };
    localStorage.setItem("users", JSON.stringify([...allusers, newUsers]));
    setAllusers(allusers.concat(newUsers));

    console.log("Localstorage:", JSON.parse(localStorage.getItem("users")));
  };

  useEffect(() => {
    console.log("Localstorage:", JSON.parse(localStorage.getItem("users")));
    if (localStorage.getItem("users")) {
      setAllusers(JSON.parse(localStorage.getItem("users")));
    }
  }, []);

  return (
    <div>
      <form>
        <input type="text" name="user" onChange={handleName} />
        <input type="text" name="email" onChange={handleEmail} />
        <button onClick={save}>Save</button>
        <p>{JSON.stringify(allusers)}</p>
      </form>
    </div>
  );
};

export default App;


As You inquired in the comment section, here is how you can implement the Update functionality:

Final Output:

在此处输入图像描述

Full source code:

import React, { useState, useEffect } from "react";
import "./style.css";
const App = () => {
  const [allusers, setAllusers] = useState([]);
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [id, setId] = useState(null);

  const handleName = e => {
    setName(e.target.value);
  };

  const handleEmail = e => {
    setEmail(e.target.value);
  };
  const save = e => {
    e.preventDefault();
    let newUsers = {
      id: Math.floor(Math.random() * 100000),
      name: name,
      email: email
    };
    localStorage.setItem("users", JSON.stringify([...allusers, newUsers]));
    setAllusers(allusers.concat(newUsers));
    console.log("Localstorage:", JSON.parse(localStorage.getItem("users")));
  };

  const setForUpdate = user => {
    setName(user.name);
    setEmail(user.email);
    setId(user.id);
  };

  const update = e => {
    e.preventDefault();
    let modifiedData = allusers.map(user => {
      if (user.id === id) {
        return { ...user, name: name, email: email };
      }
      return user;
    });

    setAllusers(modifiedData);
    localStorage.setItem("users", JSON.stringify(modifiedData));
    setId(null);
  };
  useEffect(() => {
    console.log("Localstorage:", JSON.parse(localStorage.getItem("users")));
    if (localStorage.getItem("users")) {
      setAllusers(JSON.parse(localStorage.getItem("users")));
    }
  }, []);

  return (
    <div>
      <form>
        <input value={name} type="text" name="user" onChange={handleName} />
        <input value={email} type="text" name="email" onChange={handleEmail} />
        <button disabled={!(id == null)} onClick={save}>
          Save
        </button>
        <button disabled={id == null} onClick={update}>
          Update
        </button>
      </form>
      {allusers &&
        allusers.map(user => (
          <div className="userInfo">
            <p>{user.name}</p>
            <p>{user.email}</p>
            <button onClick={() => setForUpdate(user)}>
              select for update
            </button>
          </div>
        ))}
    </div>
  );
};

export default App;

You can find the working example here: Stackblitz

you are adding only one new user while clicking on add button. You need to copy previous data also when setting all users.

Second thing setting state is async and hence your localStorage and allusers may have different value and to avoid this one you need to use useEffect to set the value.

  const add = ()=>{
          setAllusers([...allusers ,newuser])
          setID(id+1); // increase id by 1
      }

useEffect(() => {
localStorage.setItem('users',JSON.stringify(allusers))
},[allusers])

()=>handleChange is a function that takes no arguments and returns the handleChange function. You probably want () => handleChange() , which would take no arguments and INVOKE handleChange.

You are trying to save allusers to the localStorage right after setAllUsers() but setState is asynchronous . The value does not have to be updated on the next line. You can read more about it at reactjs.org, Why is setState giving me the wrong value? .

I would recommend to use useEffect .

const add=()=> {
    setAllusers([... allusers ,newuser])
}

useEffect(()=>{
   // this is called only if the variable `allusers` changes
   // because I've specified it in second argument of useEffect
   localStorage.setItem('users',JSON.stringify(allusers))
}, [allusers]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM