React redux 工具包'无法设置未定义的属性(设置 'check')

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

我尝试用 React 和 Redux Toolkit 制作一个待办事项列表,我搜索了这个错误很多次,但仍然没有解决问题的答案。

我认为我的 action.payload 定义明确。 removeItem、toggleItem 工作正常,但我只能使用其中之一。当我添加 toggleItem 函数时,我收到以下错误

Cannot set properties of undefined (setting 'check')

这是我在 stackblitz 上的完整代码 https://stackblitz.com/edit/react-ts-bqmjz1?file=redux%2Ffeatures%2FtodoSlice.ts

createSlice.ts 文件

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;

当您单击 cross 图标时,单击事件也会传播到父元素 li。所以,当你点击交叉时,首先 handleRemove 会被调用。然后, handleToggle 将被调用。但是,在调用 handleToggle 时,该项目已经从列表中删除,因此,您无法将项目的 check 属性 更改为 const index = state.findIndex((item) => item.id === action.payload.id);toggleCheck 函数中将是 -1 并且在索引 -1.

处没有项目

要解决此问题,您可以在 handleRemove 函数中执行以下操作:

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

因此,如果您单击 cross 图标,它不会将单击事件传播到父 li 事件并且不会调用 handleToggle