Right now I can reflect changes of total price if quantity changes. here is an example what I am doing now:
price of every single item
quantity {2} {200}
quantity {2} {100}
total: price = 600
Here is my cart slice:
const cartSlice = createSlice({
name: 'cart',
initialState: {
items: [],
total: 0,
},
reducers: {
addItem(state, action) {
const { id, title, price, size, color, image, quantity = 1 } = action.payload;
const existingItem = state.items.find(item => item.id === id);
if (existingItem) {
existingItem.quantity += quantity;
} else {
state.items.push({ id, title, price, size, color, image, quantity });
}
state.total += price * quantity;
},
removeItem(state, action) {
const { id, quantity = state.quantity } = action.payload;
const existingItem = state.items.find(item => item.id === id);
if (existingItem) {
if (existingItem.quantity > quantity) {
existingItem.quantity -= quantity;
} else {
state.items = state.items.filter(item => item.id !== id);
}
state.total -= existingItem.price * quantity;
}
},
removeSingleItem(state, action) {
const { id, quantity = 1 } = action.payload;
const existingItem = state.items.find(item => item.id === id);
if (existingItem) {
if (existingItem.quantity > quantity) {
existingItem.quantity -= quantity;
} else {
state.items = state.items.filter(item => item.id !== id);
}
state.total -= existingItem.price * quantity;
}
},
},
});
export const {
addItem,
removeItem,
addSingleItem,
removeSingleItem
} = cartSlice.actions;
export default cartSlice.reducer;
My expected result will be:
price of every single item
quantity {2} {400}
quantity {2} {200}
total: price = 600
2
Answers
You don’t need a
total
in state. You can derive that from theitems
array. Read more about defining a minimal representation of state here.So you should remove any mention of
total
in your slice.After that, once you update the
items
array with quantity and price, you can use a selector to get the total from that.Here we’re using a selector which takes
state
as an argument, which allows us to access thecart
slice. From thecart
slice we access theitems
array and use thereduce
array method to derive the total quantity.React state should be the minimum data it takes to represent the "state"; it’s considered a bit of a React anti-pattern to store derived state in state. In this case a cart total can be computed directly from the
state.cart.items
array.Example:
If you want or need to you can memoize the total using the
useMemo
hook.redux-toolkit
also exportsreselect
functions. You could usecreateSelector
to create a memoized selector function. In thecartSlice
file create an input selector to select thestate.cart.items
array and then create the memoized selector`.Remove the
total
state and logic from the cart slice.