具有 React 状态的本地存储
Localstorage with React States
我正在使用 Localstorage 和 States 更新用户的购物车,但在用户重新加载页面之前不会发生更新。我的代码如下所示:
const [cart, setCart] = useState([])
useEffect(()=>{
const data = localStorage.getItem('cart')
setCart(JSON.parse(data))
}, [])
我在页面加载时设置用户的购物车。
现在,当用户增加商品的数量时,例如,ONE 购物车商品将如下所示:
const singleCartItem = {
qty: 10,
color: 'red'
size: 's'
productid: 'asdasd123213'
}
这是我用来更新商品数量的函数:
const incrementQty = (type, id, qty) => {
incart.forEach(el=>{
if(el.id === id) {
const index = incart.indexOf(el)
incart[index].qty = qty + 1
localStorage.setItem('cart', JSON.stringify(cart))
}
})
}
问题来了。我知道 localStorage 在页面重新加载之前不会再次更新,但我该如何实现?
在 localStorage 中更新购物车后,只需像在 useEffect
中一样再次设置状态。在这种情况下,您可以创建一个新函数并重新使用它:
const loadCart = () => {
const data = localStorage.getItem('cart') || []
setCart(JSON.parse(data))
}
然后在 useEffect
和 incrementQty
结束时调用 loadCart()
。
编辑
我在 localStorage.getItem
之后添加了 || []
以防 returns 为 null,因此这种情况下的默认值将是一个空数组。
问题
主要问题是您正在改变本地状态而不是更新它。正是由于这种突变,您才t/can在重新加载页面并且重新获取您保留的购物车数据之前看不到“更新的”购物车。
const incrementQty = (type, id, qty) => {
incart.forEach(el=>{
if(el.id === id) {
const index = incart.indexOf(el)
incart[index].qty = qty + 1 // <-- state mutation
localStorage.setItem('cart', JSON.stringify(cart))
}
})
}
一个小问题是,如果之前没有存储任何内容,从 localStorage 获取值可能 return null。 storage getItem
解决方案
你不应该直接改变状态。将前一个状态浅复制到下一个状态,记住也要浅复制任何正在更新的嵌套状态。
您还应该将更新状态的行为与将其持久化到 localStorage 分离,为此使用 useEffect
挂钩。
const incrementQty = (type, id, qty) => {
setCart(cart => cart.map(
item => item.id === id ? {
...item,
qty: item.qty + 1
} : item,
));
}
useEffect(() => {
localStorage.setItem('cart', JSON.stringify(cart))
}, [cart]);
我建议将本地购物车状态初始化抽象为一个函数。
const initializeState = () => ({
cartItems: JSON.parse(localStorage.getItem("cart")) || [],
});
const [cart, setCart] = useState(initializeState());
如果您需要继续使用 useEffect
挂钩来加载状态,首先从 localStorage 获取购物车状态,如果非空则更新 cart
状态。
useEffect(() => {
const cartState = JSON.parse(localStorage.getItem("cart"));
if (cartState) {
setState(cartState);
}
}, []);
我正在使用 Localstorage 和 States 更新用户的购物车,但在用户重新加载页面之前不会发生更新。我的代码如下所示:
const [cart, setCart] = useState([])
useEffect(()=>{
const data = localStorage.getItem('cart')
setCart(JSON.parse(data))
}, [])
我在页面加载时设置用户的购物车。
现在,当用户增加商品的数量时,例如,ONE 购物车商品将如下所示:
const singleCartItem = {
qty: 10,
color: 'red'
size: 's'
productid: 'asdasd123213'
}
这是我用来更新商品数量的函数:
const incrementQty = (type, id, qty) => {
incart.forEach(el=>{
if(el.id === id) {
const index = incart.indexOf(el)
incart[index].qty = qty + 1
localStorage.setItem('cart', JSON.stringify(cart))
}
})
}
问题来了。我知道 localStorage 在页面重新加载之前不会再次更新,但我该如何实现?
在 localStorage 中更新购物车后,只需像在 useEffect
中一样再次设置状态。在这种情况下,您可以创建一个新函数并重新使用它:
const loadCart = () => {
const data = localStorage.getItem('cart') || []
setCart(JSON.parse(data))
}
然后在 useEffect
和 incrementQty
结束时调用 loadCart()
。
编辑
我在 localStorage.getItem
之后添加了 || []
以防 returns 为 null,因此这种情况下的默认值将是一个空数组。
问题
主要问题是您正在改变本地状态而不是更新它。正是由于这种突变,您才t/can在重新加载页面并且重新获取您保留的购物车数据之前看不到“更新的”购物车。
const incrementQty = (type, id, qty) => {
incart.forEach(el=>{
if(el.id === id) {
const index = incart.indexOf(el)
incart[index].qty = qty + 1 // <-- state mutation
localStorage.setItem('cart', JSON.stringify(cart))
}
})
}
一个小问题是,如果之前没有存储任何内容,从 localStorage 获取值可能 return null。 storage getItem
解决方案
你不应该直接改变状态。将前一个状态浅复制到下一个状态,记住也要浅复制任何正在更新的嵌套状态。
您还应该将更新状态的行为与将其持久化到 localStorage 分离,为此使用 useEffect
挂钩。
const incrementQty = (type, id, qty) => {
setCart(cart => cart.map(
item => item.id === id ? {
...item,
qty: item.qty + 1
} : item,
));
}
useEffect(() => {
localStorage.setItem('cart', JSON.stringify(cart))
}, [cart]);
我建议将本地购物车状态初始化抽象为一个函数。
const initializeState = () => ({
cartItems: JSON.parse(localStorage.getItem("cart")) || [],
});
const [cart, setCart] = useState(initializeState());
如果您需要继续使用 useEffect
挂钩来加载状态,首先从 localStorage 获取购物车状态,如果非空则更新 cart
状态。
useEffect(() => {
const cartState = JSON.parse(localStorage.getItem("cart"));
if (cartState) {
setState(cartState);
}
}, []);