繁体   English   中英

useEffect 导致组件无限重新渲染

[英]useEffect causing component to re-render infinitely

我正在向愿望清单添加项目,一旦添加,我会尝试重新渲染“心”图标以在其上显示一个数字,以表明该项目已添加到愿望清单。 我想要实现的类似于 Twitter 的点赞按钮,当有人点赞帖子时,点赞的数量会立即增加。 因此,在我的情况下,当有人喜欢(愿望清单)该产品时,它会增加 Heart 图标顶部的数字。 我正在使用本地存储来获取添加到愿望清单的项目,当在效果中添加新项目时,我可以重新渲染愿望清单组件,但它会使组件无限重新渲染,这给了我一个警告Warning: Maximum update depth exceeded

这是我的效果;

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]);

如果我从依赖数组中删除愿望清单,我需要刷新页面以查看正确的项目数。 我在这里做错了什么以及解决此问题的最佳方法是什么。 谢谢!

只需从依赖项中删除愿望清单

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

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


}, []);

在这里,您在 useEffect 的依赖数组中添加了愿望清单,并且您添加了条件if (wishlistStorage.length > 0) { setWishlist(wishlistStorage); } if (wishlistStorage.length > 0) { setWishlist(wishlistStorage); } ,因为再次设置愿望清单会导致重新渲染并再次触发 useEffect 。

如果我理解正确,并且您仅在初始渲染时需要它,那么您可以简单地从依赖数组中删除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);
     }
  }
}, []);

您可以从依赖数组中删除愿望清单变量。

当您调用setWishlist时,它会更新 state,依赖数组将检查它是否已更改并再次调用 useEffect,从而无限循环。

使用空的依赖数组,它只会在您的组件挂载、从本地存储中获取数据并初始化您的应用程序时运行。 从那里开始,您只需要在本地处理 state 并使用任何新的愿望清单项目更新本地存储,但 useEffect 似乎仅用于初始化。

您使用wishlist作为useEffect hooks 的deps,当wishlist缓存存在时, wishlistStorage是从本地存储JSON 字符串解析的object。 然后,您调用setWishlist(wishlistStorage) ,导致钩子重新渲染, wishlist将有一个新的引用。 当其依赖关系发生变化时, useEffect将再次执行。 这就是无限重新渲染的原因。

您可以使用惰性初始 state

initialState参数是在初始渲染期间使用的 state。 在随后的渲染中,它被忽略。 如果初始 state 是昂贵计算的结果,您可以提供 function 代替,它将仅在初始渲染时执行

如果 state 存在,则使用本地存储中的缓存初始化,否则返回默认值。

例如:

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

您在 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