Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

React redux toolkit 'Cannot set properties of undefined (setting 'check')

Im try to make a todo list with React and Redux Toolkit, i searching for this error so many times but still don’t have a answer to solve a problem.

I think my action.payload is well defined. removeItem, toggleItem is worked fine, but i can only using one of them. When i add toggleItem function, i received the following error

Cannot set properties of undefined (setting 'check')

Here are my full code on stackblitz https://stackblitz.com/edit/react-ts-bqmjz1?file=redux%2Ffeatures%2FtodoSlice.ts

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

createSlice.ts file

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

const todoSlice = createSlice({
  name: 'todo',
  initialState: [],
  reducers: {
    addItem: (state, action: PayloadAction<Todo>) => {
      const newItem = {
        id: new Date().getTime().toString(),
        title: action.payload.title,
        check: action.payload.check,
      };
      state.unshift(newItem);
    },
    removeItem: (state, action: PayloadAction<Todo>) => {
      return state.filter((item) => item.id !== action.payload.id);
    },

    //Toggle check 
    toggleCheck: (state, action: PayloadAction<Todo>) => {
      const index = state.findIndex((item) => item.id === action.payload.id);
      state[index].check = action.payload.check;
    },
  },
});

export const { addItem, removeItem, toggleCheck } = todoSlice.actions;

export default todoSlice.reducer;

**TodoItem.tsx **

const TodoItem = ({ item }) => {
  const dispatch = useDispatch();

  const handleRemove = () => {
    dispatch(removeItem({ id: item.id }));
  };

  const handleToggle = () => {
    dispatch(toggleCheck({ id: item.id, check: !item.check }));
  };

  return (
    <li
      className={`border border-2 list-group-item my-2 ${
        item.check ? 'border-primary text-primary' : 'border-dark'
      }`}
      onClick={handleToggle}
    >
      <div className="d-flex justify-content-between align-items-center">
        <h4>{item.title}</h4>
        <i onClick={handleRemove} className="fas fa-times text-danger"></i>
      </div>
    </li>
  );
};

export default TodoItem;

>Solution :

When you click the cross icon, the click event is also propagated to the parent element li. So, when you click on cross, first handleRemove will be called. And then, handleToggle will be called. But, by the time handleToggle is called, the item is already removed from the list and hence, you are not able to change the check property of the item as const index = state.findIndex((item) => item.id === action.payload.id); will be -1 in the toggleCheck function and there is no item at index -1.

To fix this, you can do the following in handleRemove function:

const handleRemove = (e) => {
  e.stopPropagation();
  dispatch(removeItem({ id: item.id }));
};

So, if you click on cross icon, it won’t propagate the click event to the parent li event and handleToggle won’t be invoked.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading