Home > other >  "Can't read properties of 'undefined'" after excecuting an action with Redu
"Can't read properties of 'undefined'" after excecuting an action with Redu

Time:06-18

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
  );
}
  • Related