我在ReactJS中有这个函数。当用户打开主页时,显示来自数据库的好条目数。但是当我刷新页面时,计数从0+1开始。这里的错误在哪里?
const [user, setUser] = useState({ id: "", name: "", email: "", entries: 0, joined: "", });
const onButtonSubmit = () => {
setImageUrl(input);
fetch("http://localhost:3000/imageurl", {
method: "post",
headers: {
"Content-Type": "application/json",
Authorization: "bearer " + localStorage.getItem("token"),
},
body: JSON.stringify({
input: input,
}),
})
.then((response) => response.json())
.then((response) => {
if (response) {
setUser((prev) => {
localStorage.setItem(
"user",
JSON.stringify({
...JSON.parse(localStorage.getItem("user")),
entries: prev.entries + 1,
})
);
return { ...prev, entries: prev.entries + 1 };
});
}
displayPredictions(handleApiPredictions(response));
})
.catch((err) => console.log(err));
};
怎么回事?
const [user, setUser] = useState({ id: "", name: "", email: "", entries: 0, joined: "", });
首先,在使用entries: 0
加载页面时初始化状态。
:
JSON.stringify({
...JSON.parse(localStorage.getItem("user")),
entries: prev.entries + 1,
})
您从本地存储中获取项目。并与之前用entries: 0
初始化的状态合并。
基本上就是这么做的
{
...({ entries: 123 }),
entries: ({ entries: 0 }).entries + 1
}
从0
开始的第二个entries
覆盖了第一个。
一个简单的修复
要修复它,只需从本地存储初始化您的状态。
const [user, setUser] = useState(
localStorage.getItem('user') ??
{ id: "", name: "", email: "", entries: 0, joined: "", }
);
如果本地存储中没有任何内容,则返回到初始状态。
现在在setter中,你根本不需要从本地存储中获取。
setUser((prev) => {
const newUserState = { ...prev, entries: prev.entries + 1 }
localStorage.setItem("user", JSON.stringify(newUserState))
return newUserState
})
更好的方法
不建议让状态设置器直接产生副作用(比如写入本地存储)。如果从其他函数更新这个对象呢?你必须复制你的代码保存到本地存储。
更正确的方法是使用effect来保持本地存储与来自任何源的任何更改保持同步。
可能看起来像这样:
// Initialize state with local storage item, or fallback.
// Use a function for initial state so that fetching from
// local storage only happens once.
const [user, setUser] = useState(() =>
localStorage.getItem('user') ??
{ id: "", name: "", email: "", entries: 0, joined: "", }
);
// Writes to local storage after the `user` state is set.
useEffect(() => {
localStorage.setItem("user", JSON.stringify(user))
}, [user])
// Now when you set the state, all you need to do is:
setUser((prev) => {
return { ...prev, entries: prev.entries + 1 };
});