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.