const Component = ()=>{
const [list, setList] = useState(getLocalStorage());
const [isEditing, setIsEditing] = useState(false);
const [itemToEdit, setItemToEdit] = useState();
const refContainer = useRef(null);
const putLocalStorage = () => {
localStorage.setItem("list", JSON.stringify(list));
};
const editItem = (id) => {
refContainer.current.focus();
setItemToEdit(() => {
return list.find((item) => item.id === id);
});
setIsEditing(true);
};
const handleSubmit = (e)=>{
e.preventDefault();
let nameValue = refContainer.current.value;
if (isEditing){
setList(list.map((item)=>{
if (item.id === itemToEdit.id){
return {...item, name: nameValue};
}
else {
return item;
}
);
}
else {
let newItem = {
id: new Date().getItem().toString(),
name: nameValue,
}
setList([...list, newItem])
}
nameValue="";
setIsEditing(false);
}
useEffect(() => {
putLocalStorage();
}, [list]);
return (
<div>
<form onSubmit={handleSubmit}>
<input type="text" ref={refContainer} defaultValue={isEditing ? itemToEdit.name : ""}/>
<button type="submit">submit</button>
</form>
<div>
{list.map((item) => {
const { id, name } = item;
return (
<div>
<h2>{name}</h2>
<button onClick={() => editItem(id)}>edit</button>
<button onClick={() => deleteItem(id)}>
delete
</button>
</div>
);
})}
</div>
</div>
)
}
So this part:
<input type="text" ref={refContainer} defaultValue={isEditing ? itemToEdit.name : ""} />
I want to show to users what they are editing by displaying the itemToEdit on the input.
It works on the first time when the user clicks edit button But after that, the defaultValue does not change to itemToEdit
Do you guys have any idea for the solution? (i could use controlled input instead, but i want to try it with useRef only)
Otherwise, placeholder will be the only solution...
CodePudding user response:
The defaultValue property only works for inicial rendering, that is the reason that your desired behavior works one time and then stops. See a similar question here: React input defaultValue doesn't update with state
One possible solution still using refs is to set the itemToEdit name directly into the input value using ref.current.value.
const editItem = (id) => {
refContainer.current.focus();
setItemToEdit(() => {
const item = list.find((item) => item.id === id);
refContainer.current.value = item.name;
return item;
});
setIsEditing(true);
};