React:将状态设置为本地存储
React: Setting state to local storage
我正在请求帮助将 cartItems
状态设置为本地存储,这样当我从不刷新时,我仍然可以获得这些项目。
import React, { createContext, useState } from 'react';
export const AppContext = createContext();
export function Context(props) {
const [cartItems, setCartItems] = useState([]);
const cart = (item) => {
const exist = cartItems.find((x) => x.id === item.id);
if (!exist) {
setCartItems([...cartItems, { ...item }]);
} else {
alert('Item Already Taken');
}
};
const onAdd = (items) => {
console.log(cartItems);
const exist = cartItems.find((x) => x.id === items.id);
if (exist) {
setCartItems(
cartItems.map((x) =>
x.id === items.id ? { ...exist, qty: exist.qty + 1 } : x,
),
);
console.log(cartItems);
} else {
console.log(items);
setCartItems([...cartItems, { ...items, qty: 1 }]);
}
};
const onRemove = (product) => {
const exist = cartItems.find((x) => x.id === product.id);
if (exist.qty === 1) return;
setCartItems(
cartItems.map((x) =>
x.id === product.id ? { ...exist, qty: exist.qty - 1 } : x,
),
);
};
const onDeleted = (product) => {
if (window.confirm('Do you want to delete this product?')) {
setCartItems(cartItems.filter((x) => x.id !== product.id));
}
};
const itemPrice =
cartItems && cartItems.reduce((a, c) => a + c.qty * c.price, 0);
const delieveryPrice = '3000';
// eslint-disable-next-line
const totalPrice =
parseInt(itemPrice) + (itemPrice && parseInt(delieveryPrice));
return (
<AppContext.Provider
value={{
cartItems,
setCartItems,
onAdd,
onRemove,
cart,
onDeleted,
itemPrice,
totalPrice,
delieveryPrice,
}}
>
{props.children}
</AppContext.Provider>
);
}
我通常做的是设置一个文件来处理 localStorage,所以在你的情况下,cart.services.js
。在该文件中,您可以创建接收、保存、读取、修改等 localStorage 的函数。
像这样:
const getCart = () => {
return JSON.parse(localStorage.getItem("cart"));
};
const setCart = (cart) => {
localStorage.setItem("cart", JSON.stringify(cart));
};
const removeUser = () => {
localStorage.removeItem("cart");
};
显然,您可能需要一些更高级的逻辑来根据之前的状态等添加项目,但基本逻辑就是这样,而且非常简单。
更多信息:https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
您可以通过创建一个 customHook 来使用 localStorage 中的值初始化状态并在每次更新时将状态写入 localStorage 来实现您的目标,如下所示:
import * as React from 'react'
function useLocalStorageState(
key,
defaultValue = '',
{serialize = JSON.stringify, deserialize = JSON.parse} = {},
) {
const [state, setState] = React.useState(() => {
const valueInLocalStorage = window.localStorage.getItem(key)
if (valueInLocalStorage) {
try {
return deserialize(valueInLocalStorage)
} catch (error) {
window.localStorage.removeItem(key)
}
}
return typeof defaultValue === 'function' ? defaultValue() : defaultValue
})
const prevKeyRef = React.useRef(key)
React.useEffect(() => {
const prevKey = prevKeyRef.current
if (prevKey !== key) {
window.localStorage.removeItem(prevKey)
}
prevKeyRef.current = key
window.localStorage.setItem(key, serialize(state))
}, [key, state, serialize])
return [state, setState]
}
并像这样在您的组件中使用它:
const [cartItems, setCartItems] = useLocalStorageState('cartItems',[]);
You use can use localStorage.setItem().but since you have a list of items, you will first stringify it while saving and parsing when you fetch it back.
import React, { createContext, useState } from 'react';
export const AppContext = createContext();
export function Context(props) {
const [cartItems, setCartItems] = useState([]);
const onAdd = (items) => {
const tempItems = [...cartItems];
const exist = cartItems.findIndex((x) => x.id === items.id);
console.log(exist);
if (exist >= 0) {
tempItems[exist].qty = tempItems[exist].qty + 1;
}
else {
// setCartItems([...cartItems, { ...items, qty: 1 }]);
tempItems.push(items)
}
setCartItems(tempItems)
localStorage.setItem("cart" , JSON.stringify(tempItems))
};
//to fetch data
const getCart = () => {
const FetchedcartItems = localStorage.getItem("cart");
if (FetchedcartItems) {
const parsedCartItems = JSON.parse(FetchedcartItems);
console.log(parsedCartItems);
setCartItems(parsedCartItems);
}
};
useEffect(() => {
getCart();
}, []);
return (
<AppContext.Provider
value={{
cartItems,
setCartItems,
onAdd,
onRemove,
cart,
onDeleted,
itemPrice,
totalPrice,
delieveryPrice,
}}
>
{props.children}
</AppContext.Provider>
);
}
我正在请求帮助将 cartItems
状态设置为本地存储,这样当我从不刷新时,我仍然可以获得这些项目。
import React, { createContext, useState } from 'react';
export const AppContext = createContext();
export function Context(props) {
const [cartItems, setCartItems] = useState([]);
const cart = (item) => {
const exist = cartItems.find((x) => x.id === item.id);
if (!exist) {
setCartItems([...cartItems, { ...item }]);
} else {
alert('Item Already Taken');
}
};
const onAdd = (items) => {
console.log(cartItems);
const exist = cartItems.find((x) => x.id === items.id);
if (exist) {
setCartItems(
cartItems.map((x) =>
x.id === items.id ? { ...exist, qty: exist.qty + 1 } : x,
),
);
console.log(cartItems);
} else {
console.log(items);
setCartItems([...cartItems, { ...items, qty: 1 }]);
}
};
const onRemove = (product) => {
const exist = cartItems.find((x) => x.id === product.id);
if (exist.qty === 1) return;
setCartItems(
cartItems.map((x) =>
x.id === product.id ? { ...exist, qty: exist.qty - 1 } : x,
),
);
};
const onDeleted = (product) => {
if (window.confirm('Do you want to delete this product?')) {
setCartItems(cartItems.filter((x) => x.id !== product.id));
}
};
const itemPrice =
cartItems && cartItems.reduce((a, c) => a + c.qty * c.price, 0);
const delieveryPrice = '3000';
// eslint-disable-next-line
const totalPrice =
parseInt(itemPrice) + (itemPrice && parseInt(delieveryPrice));
return (
<AppContext.Provider
value={{
cartItems,
setCartItems,
onAdd,
onRemove,
cart,
onDeleted,
itemPrice,
totalPrice,
delieveryPrice,
}}
>
{props.children}
</AppContext.Provider>
);
}
我通常做的是设置一个文件来处理 localStorage,所以在你的情况下,cart.services.js
。在该文件中,您可以创建接收、保存、读取、修改等 localStorage 的函数。
像这样:
const getCart = () => {
return JSON.parse(localStorage.getItem("cart"));
};
const setCart = (cart) => {
localStorage.setItem("cart", JSON.stringify(cart));
};
const removeUser = () => {
localStorage.removeItem("cart");
};
显然,您可能需要一些更高级的逻辑来根据之前的状态等添加项目,但基本逻辑就是这样,而且非常简单。
更多信息:https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
您可以通过创建一个 customHook 来使用 localStorage 中的值初始化状态并在每次更新时将状态写入 localStorage 来实现您的目标,如下所示:
import * as React from 'react'
function useLocalStorageState(
key,
defaultValue = '',
{serialize = JSON.stringify, deserialize = JSON.parse} = {},
) {
const [state, setState] = React.useState(() => {
const valueInLocalStorage = window.localStorage.getItem(key)
if (valueInLocalStorage) {
try {
return deserialize(valueInLocalStorage)
} catch (error) {
window.localStorage.removeItem(key)
}
}
return typeof defaultValue === 'function' ? defaultValue() : defaultValue
})
const prevKeyRef = React.useRef(key)
React.useEffect(() => {
const prevKey = prevKeyRef.current
if (prevKey !== key) {
window.localStorage.removeItem(prevKey)
}
prevKeyRef.current = key
window.localStorage.setItem(key, serialize(state))
}, [key, state, serialize])
return [state, setState]
}
并像这样在您的组件中使用它:
const [cartItems, setCartItems] = useLocalStorageState('cartItems',[]);
You use can use localStorage.setItem().but since you have a list of items, you will first stringify it while saving and parsing when you fetch it back.
import React, { createContext, useState } from 'react';
export const AppContext = createContext();
export function Context(props) {
const [cartItems, setCartItems] = useState([]);
const onAdd = (items) => {
const tempItems = [...cartItems];
const exist = cartItems.findIndex((x) => x.id === items.id);
console.log(exist);
if (exist >= 0) {
tempItems[exist].qty = tempItems[exist].qty + 1;
}
else {
// setCartItems([...cartItems, { ...items, qty: 1 }]);
tempItems.push(items)
}
setCartItems(tempItems)
localStorage.setItem("cart" , JSON.stringify(tempItems))
};
//to fetch data
const getCart = () => {
const FetchedcartItems = localStorage.getItem("cart");
if (FetchedcartItems) {
const parsedCartItems = JSON.parse(FetchedcartItems);
console.log(parsedCartItems);
setCartItems(parsedCartItems);
}
};
useEffect(() => {
getCart();
}, []);
return (
<AppContext.Provider
value={{
cartItems,
setCartItems,
onAdd,
onRemove,
cart,
onDeleted,
itemPrice,
totalPrice,
delieveryPrice,
}}
>
{props.children}
</AppContext.Provider>
);
}