useEffect 中的状态第二次争论无限循环
state in useEffect second arguement Infinite loop
我有一小段代码,我想我做错了
const [orders, setOrders] = useState([])
useEffect(() => {
fetch('/getOrders',{
headers:{
"Content-Type":"application/json",
"Authorization": "Bearer "+localStorage.getItem("jwt")
}
}).then(res=>res.json())
.then(orderList=>{
setOrders(orderList)
//console.log("myAdmin",orderList)
}).catch(err=>{
console.log("Error in Catch",err)
})
}, [orders])
这里的数据是自己超时更新的,我希望每次获取的数据与现有状态不同时更新我的状态,但无论数据是否不同,状态都会不断更新,使组件重新无限渲染。有解决办法吗?
基本上[orders]
在您的代码中意味着:每次订单更改时调用useEffect内部的内容,并且每次调用useEffect时,它都会再次更新订单...然后您将获得无限循环
useEffect(() => {
}, [orders])
您应该将 [orders]
更改为 []
。
res=>res.json()
将为您的对象创建一个新的引用,并且更改您对对象的引用意味着它发生了变化,例如 [1,2,3]
如果您再次通过 [1,2,3]
它不会相同的对象,即使它看起来相同。 v=[1,2,3]
,你传递 v,然后 v[0]=-1
,再次传递 v 它会被认为是相同的,因为它具有相同的引用。
解决此问题的最佳方法是根据您的情况手动比较它们,当它们不相同时,您使用 [...orders]
之类的东西,这将创建新的引用并再次调用 useEffect。
尝试使用 prevState 参数设置状态,这样您就不必包含任何依赖项。
setOrders((prevState) => ({
...prevState, orderList
}))
问题
只要效果无条件地更新其依赖数组中的值,就会导致渲染循环。
useEffect(() => {
fetch('/getOrders', { ... })
.then(res=>res.json())
.then(orderList=>{
setOrders(orderList); // <-- updates state, triggers rerender
})
.catch(err=>{
...
});
}, [orders]); // <-- updated state triggers effect callback
可能的解决方案
您似乎想要在每次组件呈现时获取,并在成功响应(200 OK)后检查 orders
数组是否实际上 不同。如果是则更新状态,否则忽略更新。
- 删除依赖数组,以便每次组件呈现时调用
useEffect
挂钩回调。
- 在访问响应 JSON 数据之前检查
fetch
请求响应是否为 ok
。
- 根据状态检查
order
响应数据。如果数组长度不同,则更新状态,否则您将需要逐个元素检查以确定数组是否不同。 *
更新效果挂钩
const [orders, setOrders] = useState([])
useEffect(() => {
fetch("/getOrders", {
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + localStorage.getItem("jwt")
}
})
.then((res) => {
if (!res.ok) {
throw new Error("Fetch is not OK");
}
return res.json();
})
.then((orderList) => {
if (orders.length !== orderList.length) {
setOrders(orderList);
} else {
for (let i = 0; i < orders.length; i++) {
// *** Your actual equality condition may be different, i.e. if they are objects ***
if (orders[i] !== orderList[i]) {
setOrders(orderList);
return;
}
}
}
})
.catch((err) => {
console.error("Error in Catch", err);
});
});
* 这是一个 O(n)
每次 检查 因此可以进行的优化也可能是 return 并存储“更新”哈希.如果哈希与之前的请求相同,则跳过状态更新。这可能就像在后端为更新生成新的 GUID 并return用数据处理它一样简单。
我有一小段代码,我想我做错了
const [orders, setOrders] = useState([])
useEffect(() => {
fetch('/getOrders',{
headers:{
"Content-Type":"application/json",
"Authorization": "Bearer "+localStorage.getItem("jwt")
}
}).then(res=>res.json())
.then(orderList=>{
setOrders(orderList)
//console.log("myAdmin",orderList)
}).catch(err=>{
console.log("Error in Catch",err)
})
}, [orders])
这里的数据是自己超时更新的,我希望每次获取的数据与现有状态不同时更新我的状态,但无论数据是否不同,状态都会不断更新,使组件重新无限渲染。有解决办法吗?
基本上[orders]
在您的代码中意味着:每次订单更改时调用useEffect内部的内容,并且每次调用useEffect时,它都会再次更新订单...然后您将获得无限循环
useEffect(() => {
}, [orders])
您应该将 [orders]
更改为 []
。
res=>res.json()
将为您的对象创建一个新的引用,并且更改您对对象的引用意味着它发生了变化,例如 [1,2,3]
如果您再次通过 [1,2,3]
它不会相同的对象,即使它看起来相同。 v=[1,2,3]
,你传递 v,然后 v[0]=-1
,再次传递 v 它会被认为是相同的,因为它具有相同的引用。
解决此问题的最佳方法是根据您的情况手动比较它们,当它们不相同时,您使用 [...orders]
之类的东西,这将创建新的引用并再次调用 useEffect。
尝试使用 prevState 参数设置状态,这样您就不必包含任何依赖项。
setOrders((prevState) => ({
...prevState, orderList
}))
问题
只要效果无条件地更新其依赖数组中的值,就会导致渲染循环。
useEffect(() => {
fetch('/getOrders', { ... })
.then(res=>res.json())
.then(orderList=>{
setOrders(orderList); // <-- updates state, triggers rerender
})
.catch(err=>{
...
});
}, [orders]); // <-- updated state triggers effect callback
可能的解决方案
您似乎想要在每次组件呈现时获取,并在成功响应(200 OK)后检查 orders
数组是否实际上 不同。如果是则更新状态,否则忽略更新。
- 删除依赖数组,以便每次组件呈现时调用
useEffect
挂钩回调。 - 在访问响应 JSON 数据之前检查
fetch
请求响应是否为ok
。 - 根据状态检查
order
响应数据。如果数组长度不同,则更新状态,否则您将需要逐个元素检查以确定数组是否不同。 *
更新效果挂钩
const [orders, setOrders] = useState([])
useEffect(() => {
fetch("/getOrders", {
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + localStorage.getItem("jwt")
}
})
.then((res) => {
if (!res.ok) {
throw new Error("Fetch is not OK");
}
return res.json();
})
.then((orderList) => {
if (orders.length !== orderList.length) {
setOrders(orderList);
} else {
for (let i = 0; i < orders.length; i++) {
// *** Your actual equality condition may be different, i.e. if they are objects ***
if (orders[i] !== orderList[i]) {
setOrders(orderList);
return;
}
}
}
})
.catch((err) => {
console.error("Error in Catch", err);
});
});
* 这是一个 O(n)
每次 检查 因此可以进行的优化也可能是 return 并存储“更新”哈希.如果哈希与之前的请求相同,则跳过状态更新。这可能就像在后端为更新生成新的 GUID 并return用数据处理它一样简单。