我试图用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
。