简体   繁体   English

useEffect 导致组件无限重新渲染

[英]useEffect causing component to re-render infinitely

I am adding items to the wishlist and once it is added I am trying to re-render the Heart icon to have a number on it to indicate that the Item has been added to the wishlist.我正在向愿望清单添加项目,一旦添加,我会尝试重新渲染“心”图标以在其上显示一个数字,以表明该项目已添加到愿望清单。 What I want to achieve is similar to Twitter's like button, when someone likes the post the number of likes increases immediately.我想要实现的类似于 Twitter 的点赞按钮,当有人点赞帖子时,点赞的数量会立即增加。 So, in my case when someone likes (wishlists) the product it will increase the number on top of Heart icon.因此,在我的情况下,当有人喜欢(愿望清单)该产品时,它会增加 Heart 图标顶部的数字。 I am using local storage to get the items that are added to the wishlist, and I can re-render the Wishlist component when a new Item is added inside the effect but it makes the component to re-render infinitely which is giving me a warning of Warning: Maximum update depth exceeded我正在使用本地存储来获取添加到愿望清单的项目,当在效果中添加新项目时,我可以重新渲染愿望清单组件,但它会使组件无限重新渲染,这给了我一个警告Warning: Maximum update depth exceeded

Here is my effect;这是我的效果;

const [wishlist, setWishlist] = React.useState([]);

  React.useEffect(() => {
     if (typeof window !== "undefined") {
       const wishlistStorage =
       localStorage.getItem("wishlist") === null
       ? []
       : [...JSON.parse(localStorage.getItem("wishlist"))];

     if (wishlistStorage.length > 0) {
       setWishlist(wishlistStorage);
  }
}


}, [wishlist]);

If I remove the wishlist from dependancy array, I need to refresh the page to see the correct number of items.如果我从依赖数组中删除愿望清单,我需要刷新页面以查看正确的项目数。 What am I doing wrong here and what would be the best way to approach this.我在这里做错了什么以及解决此问题的最佳方法是什么。 Thank you!谢谢!

just remove the wishlist from the dependencies只需从依赖项中删除愿望清单

     React.useEffect(() => {
     if (typeof window !== "undefined") {
       const wishlistStorage =
       localStorage.getItem("wishlist") === null
       ? []
       : [...JSON.parse(localStorage.getItem("wishlist"))];

     if (wishlistStorage.length > 0) {
       setWishlist(wishlistStorage);
  }
}


}, []);

Here you have add wishlist in dependency array of useEffect and in that you have added condition if (wishlistStorage.length > 0) { setWishlist(wishlistStorage); }在这里,您在 useEffect 的依赖数组中添加了愿望清单,并且您添加了条件if (wishlistStorage.length > 0) { setWishlist(wishlistStorage); } if (wishlistStorage.length > 0) { setWishlist(wishlistStorage); } , because setting again the wishlist it will cause re-render and again useEffect will be triggered. if (wishlistStorage.length > 0) { setWishlist(wishlistStorage); } ,因为再次设置愿望清单会导致重新渲染并再次触发 useEffect 。

If I understand correctly, and you need this only for the initial render, then you can simply remove wishlist from the dependency array.如果我理解正确,并且您仅在初始渲染时需要它,那么您可以简单地从依赖数组中删除wishlist

const [wishlist, setWishlist] = React.useState([]);

React.useEffect(() => {
   if (typeof window !== "undefined") {
     const wishlistStorage =
     localStorage.getItem("wishlist") === null
     ? []
     : [...JSON.parse(localStorage.getItem("wishlist"))];

     if (wishlistStorage.length > 0) {
       setWishlist(wishlistStorage);
     }
  }
}, []);

You can remove the wishlist variable from the dependency array.您可以从依赖数组中删除愿望清单变量。

When you call setWishlist , it'll update the state, the dependency array will check that it has changed and will call the useEffect once more, thus the infinite cycle.当您调用setWishlist时,它会更新 state,依赖数组将检查它是否已更改并再次调用 useEffect,从而无限循环。

With an empty dependency array, it'll only run when your component mounts, fetching the data from your local storage and initializing your app.使用空的依赖数组,它只会在您的组件挂载、从本地存储中获取数据并初始化您的应用程序时运行。 From there on, all you need is to handle the state locally and updating the localstorage with any new wishlist items, but that useEffect seems to be for initialization only.从那里开始,您只需要在本地处理 state 并使用任何新的愿望清单项目更新本地存储,但 useEffect 似乎仅用于初始化。

You use wishlist as the deps of useEffect hooks, when the wishlist cache exists, wishlistStorage is an object parsed from the local storage JSON string.您使用wishlist作为useEffect hooks 的deps,当wishlist缓存存在时, wishlistStorage是从本地存储JSON 字符串解析的object。 Then, you call setWishlist(wishlistStorage) , cause the hook re-render, the wishlist will have a new reference.然后,您调用setWishlist(wishlistStorage) ,导致钩子重新渲染, wishlist将有一个新的引用。 The useEffect will execute again when its dependencies changes.当其依赖关系发生变化时, useEffect将再次执行。 That's why re-render infinitely.这就是无限重新渲染的原因。

You could use lazy initial state您可以使用惰性初始 state

The initialState argument is the state used during the initial render. initialState参数是在初始渲染期间使用的 state。 In subsequent renders, it is disregarded.在随后的渲染中,它被忽略。 If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render如果初始 state 是昂贵计算的结果,您可以提供 function 代替,它将仅在初始渲染时执行

Use the cache from the local storage to initial your state if it exists, otherwise, returns a default value.如果 state 存在,则使用本地存储中的缓存初始化,否则返回默认值。

Eg:例如:

const [wishlist, setWishlist] = React.useState(() => {
 if (typeof window !== "undefined") {
    const wishlistStorage =
       localStorage.getItem("wishlist") === null
       ? []
       : [...JSON.parse(localStorage.getItem("wishlist"))];
    return wishlistStorage;
  }
  return [];
);

you are using setWishlist in useEffect that's observe wishlist, that's why it's lead you to infinity loop cuz when wishlist value changed it will execute the code in useEffect again and again so for my solution i saw localStorage in useEffect i would think it's would be only checked in first render, so you can simply remove [wishlist] -> []您在 useEffect 中使用 setWishlist 来观察愿望清单,这就是为什么当愿望清单值更改时它会导致您进入无限循环,因为它会一次又一次地执行 useEffect 中的代码,所以对于我的解决方案,我在 useEffect 中看到 localStorage 我认为它只会被检查在第一次渲染中,因此您可以简单地删除 [wishlist] -> []

  const [wishlist, setWishlist] = React.useState([]);

  React.useEffect(() => {
     if (typeof window !== "undefined") {
       const wishlistStorage =
       localStorage.getItem("wishlist") === null
       ? []
       : [...JSON.parse(localStorage.getItem("wishlist"))];

     if (wishlistStorage.length > 0) {
       setWishlist(wishlistStorage);
  }
}


}, []);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM