javascript - useEffect 和 watch 状态
问题描述
我正在尝试使用函数调用在渲染时设置项目的状态,然后观察项目状态的变化以在它们发生变化时导致重新渲染。根据建议的答案传递对对象键的引用似乎没有任何改变。我正在尝试使用钩子 useEffect() 来做到这一点。getCart() 是一个从 localStorage 检索数据的函数。代码:
const [items, setItems] = useState([]);
useEffect(() => {
setItems(getCart());
}, [items]);
我收到一个错误“超出最大更新深度。当组件在 useEffect 中调用 setState,但 useEffect 没有依赖数组,或者每次渲染时其中一个依赖项发生更改时,可能会发生这种情况。”
我了解如何通过有效地更改渲染时的项目状态来导致无限循环,然后这会导致重新渲染等等。我将如何解决这个问题,这可能使用 useEffect 吗?谢谢。
编辑:编辑 localStorage 的代码
export const updateItem = (productId, count) => {
let cart = [];
if (typeof window !== 'undefined') {
if (localStorage.getItem('cart')) {
cart = JSON.parse(localStorage.getItem('cart'));
}
cart.map((product, index) => {
if (product._id === productId) {
cart[index].count = count;
}
})
localStorage.setItem('cart', JSON.stringify(cart));
}
}
解决方案
正如评论中所建议的,解决方案是将setItems
调用移出useEffect
并在其他地方调用它以及updateItem
保存/更新数据的函数localStorage
:
// cart.js
export const updateItem = (productId, count) => {
// see implementation above
}
// App.js
function App() {
const [items, setItems] = useState([])
useEffect(() => {
const cartItems = getCart()
setItems(cartItems)
// pass an empty dependency array so that this hook
// runs only once and gets data from `localStorage` when it first mounts
}, [])
const handleQuantityChange = (data) => {
// this will update `localStorage`, get new cart state
// from `localStorage`, and update state inside of this component
updateItem(data.productId, data.count)
const currentCart = getCart()
setItems(currentCart)
}
return (
<div>
{...}
<button onClick={() => handleQuantityChange(...)>
Add more
</button>
</div>
)
}
这样,调用setItems
就可以了,因为它只会在单击按钮时触发。
此外,由于useEffect
需要一个空的依赖数组,它不会再导致maxiumum update depth exceeded
错误,因为它只会运行一次以在localStorage
渲染后立即获取初始状态,然后该组件的本地状态将在handleQuantityChange
处理程序中更新。