试图坚持我的反应状态并在渲染上获得无限循环
Trying to persist my react state and getting infinite loop on render
当尝试使用 localStorage 来保存我的反应状态时,我得到了无限的重新渲染,我可以在开发工具中看到状态不断地被填充然后未填充。
我知道是我对 useEffect 的使用导致了这个问题,也许是我用存储的状态填充我的地图对象的条件。
设置状态项没有问题。
检索它没有。
非常感谢任何帮助。
我的代码:
useEffect(() => {
localStorage.myCartState ? setCart(new Map(JSON.parse(localStorage.myCartState)))
:
setCart(new Map())
})
useEffect(() => {
localStorage.myCartState = JSON.stringify(Array.from(cart.entries()));
},[cart])
这是我的购物车初始状态:
const [cart, setCart] = useState(new Map())
在没有 dependency array 的情况下定义 useEffect
将导致在每次渲染时调用它。在您的 useEffect
中,您正在设置状态,这会触发渲染。这会导致无限循环。
如果您希望第一个效果仅 运行 在组件安装上,请将一个空的依赖项数组传递给它。这样的事情可能会解决问题:
useEffect(() => {
localStorage.getItem('myCartState') ? setCart(new Map(JSON.parse(localStorage.getItem('myCartState'))))
:
setCart(new Map())
, []);
有关更多信息,我建议阅读 useEffect 上的文档,其中对此进行了更详细的介绍。
除此之外,localStorage
的用法似乎不正确。当 getting/storing 数据进入 localStorage
.
时,您需要使用 getItem and setItem
无论您在 localStorage.myCartState
中检索和存储什么数据,都会在您的第一个 useEffect
挂钩内的三元操作中设置其值 true
,您在其中使用状态更新函数 setCart
,它再次更新状态导致重新渲染,再次加载第一个 useEffect
挂钩,条件再次为真并且状态发生变化,等等。
如果您在程序中仅使用一次第一个挂钩 运行,您可以传递一个空列表 []
作为挂钩的附加参数
useEffect(() => {
localStorage.myCartState ? setCart(new Map(JSON.parse(localStorage.myCartState)))
:
setCart(new Map())
}, [])
否则您可能需要考虑更改您的三元操作或携带不同的 state/variable 以导致挂钩触发而不是在每次渲染期间触发。
干杯!
让我花点时间解释一下为什么,而不仅仅是回答如何解决这个问题。
useEffect 钩子有 2 个参数。回调和依赖数组,其中数组确定何时执行回调 https://reactjs.org/docs/hooks-effect.html
不行看看后面的代码
useEffect(() => {
localStorage.myCartState ? setCart(new Map(JSON.parse(localStorage.myCartState)))
:
setCart(new Map())
})
这里你传递给你的回调一个无依赖数组,这意味着“运行 每次渲染组件时的回调”
并且在回调的底部,您正在执行 setCart(new Map())
这是状态更新。
更新状态是重新渲染的原因之一https://reactjs.org/docs/state-and-lifecycle.html,重新渲染是触发 useEffect 回调的原因,useEffect 回调正在更新状态...等等
所以,基本上您是在创建状态更新、渲染和触发回调的无限循环。
如何解决
useEffect(() => {
localStorage.myCartState ? setCart(new Map(JSON.parse(localStorage.myCartState)))
:
setCart(new Map())
})
更新您的 useEffect 以获取一个空数组以将触发器限制为第一次渲染,并注意每次您的无限重新渲染循环的原因可能是
- 没有传递 dep 数组
- 更新 dep 数组中引用的状态
当尝试使用 localStorage 来保存我的反应状态时,我得到了无限的重新渲染,我可以在开发工具中看到状态不断地被填充然后未填充。
我知道是我对 useEffect 的使用导致了这个问题,也许是我用存储的状态填充我的地图对象的条件。
设置状态项没有问题。
检索它没有。
非常感谢任何帮助。
我的代码:
useEffect(() => {
localStorage.myCartState ? setCart(new Map(JSON.parse(localStorage.myCartState)))
:
setCart(new Map())
})
useEffect(() => {
localStorage.myCartState = JSON.stringify(Array.from(cart.entries()));
},[cart])
这是我的购物车初始状态:
const [cart, setCart] = useState(new Map())
在没有 dependency array 的情况下定义 useEffect
将导致在每次渲染时调用它。在您的 useEffect
中,您正在设置状态,这会触发渲染。这会导致无限循环。
如果您希望第一个效果仅 运行 在组件安装上,请将一个空的依赖项数组传递给它。这样的事情可能会解决问题:
useEffect(() => {
localStorage.getItem('myCartState') ? setCart(new Map(JSON.parse(localStorage.getItem('myCartState'))))
:
setCart(new Map())
, []);
有关更多信息,我建议阅读 useEffect 上的文档,其中对此进行了更详细的介绍。
除此之外,localStorage
的用法似乎不正确。当 getting/storing 数据进入 localStorage
.
无论您在 localStorage.myCartState
中检索和存储什么数据,都会在您的第一个 useEffect
挂钩内的三元操作中设置其值 true
,您在其中使用状态更新函数 setCart
,它再次更新状态导致重新渲染,再次加载第一个 useEffect
挂钩,条件再次为真并且状态发生变化,等等。
如果您在程序中仅使用一次第一个挂钩 运行,您可以传递一个空列表 []
作为挂钩的附加参数
useEffect(() => {
localStorage.myCartState ? setCart(new Map(JSON.parse(localStorage.myCartState)))
:
setCart(new Map())
}, [])
否则您可能需要考虑更改您的三元操作或携带不同的 state/variable 以导致挂钩触发而不是在每次渲染期间触发。
干杯!
让我花点时间解释一下为什么,而不仅仅是回答如何解决这个问题。
useEffect 钩子有 2 个参数。回调和依赖数组,其中数组确定何时执行回调 https://reactjs.org/docs/hooks-effect.html
不行看看后面的代码
useEffect(() => {
localStorage.myCartState ? setCart(new Map(JSON.parse(localStorage.myCartState)))
:
setCart(new Map())
})
这里你传递给你的回调一个无依赖数组,这意味着“运行 每次渲染组件时的回调”
并且在回调的底部,您正在执行 setCart(new Map())
这是状态更新。
更新状态是重新渲染的原因之一https://reactjs.org/docs/state-and-lifecycle.html,重新渲染是触发 useEffect 回调的原因,useEffect 回调正在更新状态...等等
所以,基本上您是在创建状态更新、渲染和触发回调的无限循环。
如何解决
useEffect(() => {
localStorage.myCartState ? setCart(new Map(JSON.parse(localStorage.myCartState)))
:
setCart(new Map())
})
更新您的 useEffect 以获取一个空数组以将触发器限制为第一次渲染,并注意每次您的无限重新渲染循环的原因可能是
- 没有传递 dep 数组
- 更新 dep 数组中引用的状态