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