I'm making a Shopping List App with React/Redux. I'm having truble removing an item from a list. After excecuting the 'removeItem' action the page can no longer read the object that is the list (which was previously stored in local state and coul'd be read before excecuting the action).
I've tried storing the list object in a const variable and a local state using the useEffect hook but it still breaks.
JSX
const { id } = useParams();
const shoppingLists = useSelector((state) => state.shoppingLists);
const findList = shoppingLists.find((list) => list.listId === id);
const [selectedList, setSelectedList] = useState({});
useEffect(() => {
setSelectedList(findList);
});
const removeItemForm = (item) => {
const { itemName, itemId } = item;
dispatch(removeItem({ itemName, itemId, listId: id }));
};
<div className="listHeading mb-4">
<h2>{selectedList.listName}</h2> //Line that breaks
</div>
Reducer
const shoppingListsSlice = createSlice({
name: "shoppingLists",
initialState: [],
reducers: {
createList(state, action) {
state.push({
listId: uuidv4(),
listName: action.payload,
items: [],
color: "",
createdAt: Date(),
});
addItem(state, action) {
state
.find((list) => list.listId === action.payload.listId)
.items.push({
itemId: uuidv4(),
itemName: action.payload.itemName,
isBought: false,
});
},
removeItem(state, action) {
return state
.find((list) => list.listId === action.payload.listId)
.items.filter((item) => item.itemId !== action.payload.itemId);
},
CodePudding user response:
if just want to remove the item from the cart then your list state id and current item id filter data store into the state again that's it. and you find index first directly apply filter method.
CodePudding user response:
Your issue is with your removeItem
reducer. Whatever you return from a reducer will become the new state value. In this case, you're returning an array of filtered items
from a particular shopping list object, which isn't what you want to set your state to, as it really should still be an array of lists, not items. When that happens, shoppingLists
will instead refer to your items
array, which will cause the .find()
to set findList
to undefined
. Since redux-toolkit uses immer, you can do mutable updates within your reducer to keep things easier to read:
removeItem(state, action) {
const list = state.find((list) => list.listId === action.payload.listId);
list.items = list.items.filter((item) => item.itemId !== action.payload.itemId);
}
the immutable approach would be to .map()
your shopping list state and return a new list objct which a filtered items
arrays:
removeItem(state, action) {
return state.map((list) => list.listId === action.payload.listId
? {...list, items: list.items.filter((item) => item.itemId !== action.payload.itemId)}
: list
);
}