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



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

我认为我的行动纲领很明确。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

最新更新