Fetch 和 setState 哪个先执行?
Which one is executed first Fetch or setState?
我试图从 HTML 表单将数据从前端(React)发送到后端(express),并在提交后清除字段。这就是它的样子。这里的 item 和 amount 是受控组件的状态。所以我的问题是因为我在获取状态之前更新状态而不是更新它。由于 fetch 和 setState 是异步的,因此将先执行哪一个。即使我在 fetch 之后写状态更新, fetch 似乎也是先执行的。但我不明白怎么办?
function onSub(e, setList, list) {
e.preventDefault();
setList([...list, { item, amount }]);
setItem("");
setAmt("");
fetch("http://localhost:3001/addData", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title: item, amt: amount }),
})
.then((res) => res.text())
.then((data) => {
console.log(data);
});
}
他们在赛跑。通常你会期望状态首先被设置,因为状态设置器只在 DOM 中本地操作,而 fetch
必须与服务器对话,但它们在竞争中并且你不能指望哪一个会赢得比赛。
如果你想控制哪个先发生,你需要明确地做到这一点。让 fetch
首先完成会更容易,因为您可以等到 fetch
过程结束后再调用状态设置器。这也让您有机会处理 fetch
故障(例如暂时性网络错误)而不会丢失用户提供的信息,因为您已经将其从状态中清除:
function onSub(e, setList, list) {
e.preventDefault();
fetch("http://localhost:3001/addData", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title: item, amt: amount }),
})
.then((res) => {
if (!res.ok) { // This check was missing
throw new Error(`HTTP error ${res.status}`);
}
return res.text();
})
.then((data) => {
console.log(data);
setList([...list, { item, amount }]);
setItem("");
setAmt("");
})
.catch(error => {
setError(/*...some error message saying something went wrong...*/);
});
}
旁注:我解释了有关缺少支票的评论 here。为了避免编写所有样板文件,我建议使用一些方便的实用函数,例如:
export async function postJSON(url, data) {
const res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!res.ok) { // This check was missing
throw new Error(`HTTP error ${res.status}`);
}
return res;
}
那么代码应该是这样的:
function onSub(e, setList, list) {
e.preventDefault();
postJSON("http://localhost:3001/addData", { title: item, amt: amount })
.then((data) => {
console.log(data);
setList([...list, { item, amount }]);
setItem("");
setAmt("");
})
.catch(error => {
setError(/*...some error message saying something went wrong...*/);
});
}
我试图从 HTML 表单将数据从前端(React)发送到后端(express),并在提交后清除字段。这就是它的样子。这里的 item 和 amount 是受控组件的状态。所以我的问题是因为我在获取状态之前更新状态而不是更新它。由于 fetch 和 setState 是异步的,因此将先执行哪一个。即使我在 fetch 之后写状态更新, fetch 似乎也是先执行的。但我不明白怎么办?
function onSub(e, setList, list) {
e.preventDefault();
setList([...list, { item, amount }]);
setItem("");
setAmt("");
fetch("http://localhost:3001/addData", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title: item, amt: amount }),
})
.then((res) => res.text())
.then((data) => {
console.log(data);
});
}
他们在赛跑。通常你会期望状态首先被设置,因为状态设置器只在 DOM 中本地操作,而 fetch
必须与服务器对话,但它们在竞争中并且你不能指望哪一个会赢得比赛。
如果你想控制哪个先发生,你需要明确地做到这一点。让 fetch
首先完成会更容易,因为您可以等到 fetch
过程结束后再调用状态设置器。这也让您有机会处理 fetch
故障(例如暂时性网络错误)而不会丢失用户提供的信息,因为您已经将其从状态中清除:
function onSub(e, setList, list) {
e.preventDefault();
fetch("http://localhost:3001/addData", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title: item, amt: amount }),
})
.then((res) => {
if (!res.ok) { // This check was missing
throw new Error(`HTTP error ${res.status}`);
}
return res.text();
})
.then((data) => {
console.log(data);
setList([...list, { item, amount }]);
setItem("");
setAmt("");
})
.catch(error => {
setError(/*...some error message saying something went wrong...*/);
});
}
旁注:我解释了有关缺少支票的评论 here。为了避免编写所有样板文件,我建议使用一些方便的实用函数,例如:
export async function postJSON(url, data) {
const res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!res.ok) { // This check was missing
throw new Error(`HTTP error ${res.status}`);
}
return res;
}
那么代码应该是这样的:
function onSub(e, setList, list) {
e.preventDefault();
postJSON("http://localhost:3001/addData", { title: item, amt: amount })
.then((data) => {
console.log(data);
setList([...list, { item, amount }]);
setItem("");
setAmt("");
})
.catch(error => {
setError(/*...some error message saying something went wrong...*/);
});
}