我已经建立了一个电子商务应用程序,并需要购物车项目保持不变,如果用户刷新页面。我已经创建了一个切片在这个文件中的所有行动。我做了一些阅读redux-tooklit-persist,它听起来像是我的解决方案。我已经包括了reducer文件以及文件,其中包含“AddToCart”功能。
import { createSlice } from "@reduxjs/toolkit"
const initialState = {
isCartOpen: false,
cart: [],
items: []
}
export const cartSlice = createSlice({
name: "cart",
initialState,
reducers: {
setItems: (state, action) => {
state.items = action.payload
},
// Add item to cart
addToCart: (state, action) => {
state.cart = [...state.cart, action.payload.item]
},
// Remove item from cart
removeFromCart: (state, action) => {
state.cart = state.cart.filter((item) => item.id !== action.payload.id)
},
// Increase count in cart
increaseCount: (state, action) => {
state.cart = state.cart.map((item) => {
if (item.id === action.payload.id) {
item.count++
}
return item
})
},
// Decrease count in cart
decreaseCount: (state, action) => {
state.cart = state.cart.map((item) => {
if (item.id === action.payload.id && item.count > 1) {
item.count--
}
return item
})
},
setIsCartOpen: (state) => {
state.isCartOpen = !state.isCartOpen
}
}
})
//Export
export const {
setItems,
addToCart,
removeFromCart,
increaseCount,
decreaseCount,
setIsCartOpen
} = cartSlice.actions
export default cartSlice.reducer
这是我的项目.jsx
import { useState } from "react"
import { useDispatch } from "react-redux"
import { IconButton, Box, Typography, useTheme, Button } from "@mui/material"
import AddIcon from "@mui/icons-material/Add"
import RemoveIcon from "@mui/icons-material/Remove"
import { shades } from "../theme"
import { addToCart } from "../state"
import { useNavigate } from "react-router-dom"
const Item = ({ item, width }) => {
const navigate = useNavigate()
const dispatch = useDispatch()
const [count, setCount] = useState(1)
const [isHovered, setIsHovered] = useState(false)
const {
palette: { neutral }
} = useTheme()
// Destructure from attributes
const { category, price, name, image } = item.attributes
const {
data: {
attributes: {
formats: {
medium: { url }
}
}
}
} = image
return (
<Box width={width}>
<Box
position="relative"
onMouseOver={() => setIsHovered(true)}
onMouseOut={() => setIsHovered(false)}
>
<img
alt={item.name}
width="300px"
height="400px"
src={`http://localhost:1337${url}`}
onClick={() => navigate(`/item/${item.id}`)}
style={{ cursor: "pointer" }}
/>
<Box
display={isHovered ? "block" : "none"}
position="absolute"
bottom="10%"
left="0"
width="100%"
padding="0 5%"
>
<Box display="flex" justifyContent="space-between">
<Box
display="flex"
alignItems="center"
backgroundColor={shades.neutral[100]}
borderRadius="3px"
>
<IconButton onClick={() => setCount(Math.max(count - 1, 1))}>
<RemoveIcon />
</IconButton>
<Typography color={shades.primary[300]}>
{count}
</Typography>
<IconButton onClick={() => setCount(count + 1)}>
<AddIcon />
</IconButton>
</Box>
<Button
onClick={() => {
dispatch(addToCart({ item: { ...item, count } }))
}}
sx={{
backgroundColor: shades.primary[300],
color: "white"
}}
>
Add to Cart
</Button>
</Box>
</Box>
</Box>
<Box mt="3px">
<Typography variant="subtitle2" color={neutral.dark}>
{category
.replace(/([A-Z])/g, " $1")
.replace(/^./, (str) => str.toUpperCase())
}
</Typography>
<Typography>{name}</Typography>
<Typography fontWeight="bold">${price}</Typography>
</Box>
</Box>
)
}
export default Item
2条答案
按热度按时间vbkedwbf1#
redux-persist
是react
Redux状态持久性的标准。虽然您可以像Mohammad的答案那样单独初始化和持久化从&到localStorage的状态切片,但这是不明智的,因为持久化到localStorage的行为是被认为是*纯函数的副作用。
最好将其抽象为一个定制的中间件。RTK维护人员已经使使用
createListenerMiddleware
创建中间件侦听器变得相当容易。您可以创建一个中间件侦听器,它对特定的操作或条件做出React,以将存储持久化到localStorage。我建议使用
redux-persist
,如果你已经熟悉了react
和redux-toolkit
,这是一个相当快的设置/集成。示例:
此时,我还将导出一个 Package 器组件,用于呈现
react-redux
Provider
组件和redux-persist
的PersistGate
组件。现在,您可以使用
PersistedProvider
组件进行 Package ,而不是使用Provider
组件 PackageApp
组件,并将Redux存储提供给应用***,***持久化redux状态。58wvjzkj2#
我的朋友,你必须使用localStorage来存储浏览器中的数据:
在这里,每次您调度
addToCart
时,您的数据将保存在redux和localStorage中,当您刷新页面时,您的redux将填充localStorage。我只更改了其中一个Reducer,您必须根据localStorage和您的redux更改所有Redux。如果您遇到问题,请告诉我,我会向您解释。