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 数组是否实际上 不同。如果是则更新状态,否则忽略更新。

  1. 删除依赖数组,以便每次组件呈现时调用 useEffect 挂钩回调。
  2. 在访问响应 JSON 数据之前检查 fetch 请求响应是否为 ok
  3. 根据状态检查 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用数据处理它一样简单。