我正在使用本地json文件来存储一些数据,如下所示:
[
{
"name": "Sports",
"todos": [
{
"id": 1,
"title": "Play Football"
},
{
"id": 2,
"title": "Play Basketball"
}
]
},
{
"name": "Work",
"todos": [
{
"id": 3,
"title": "Study TS"
},
{
"id": 4,
"title": "Work Hard"
}
]
}
]
我制作了一个简化器,该简化器采用了以上两个类别,并在组件页面上实际显示了所有这些数据。
我现在正在尝试创建另一个reducer,以从每个类别内的todos数组中删除某个项目,但是我失败了。这是到目前为止我创建的动作和减速器
// actions
export const getCategories = () => {
return async (dispatch: Dispatch) => {
const response = await axios.get<Category[]>(url);
dispatch({
type: 'GET_ALL_CATEGORIES',
payload: response.data
});
};
};
export const deleteTodo = (id: number) => {
return {
type: 'DELETE_A_TODO',
payload: { id }
};
};
// reducers
const categoriesReducer = (state: Category[] = [], action: Action) => {
switch (action.type) {
case 'GET_ALL_CATEGORIES':
return action.payload;
case 'DELETE_A_TODO':
state.forEach(category => {
return category.todos.filter(
todo => todo.id !== action.payload.id
);
});
default:
return state;
}
};
export const reducers = combineReducers<ReduxStoreState>({
categories: categoriesReducer
});
然后在组件内部成功完成deleteTodo动作的连接,但没有任何内容被删除,状态没有差异。
我在做什么错了?
答案 0 :(得分:2)
替换
state.forEach(category => {
return category.todos.filter(
todo => todo.id !== action.payload.id
);
});
具有:
return state.map(category => {
return {
...category,
todos: category.todos.filter(todo => todo.id !== action.payload.id)
}
})
答案 1 :(得分:1)
我建议在deleteTodo
动作的有效载荷中返回类别名称或更好的ID类别索引。
在代码的当前状态下,这是解决方案之一
const categoriesReducer = (state: Category[] = [], action: Action) => {
switch (action.type) {
case 'GET_ALL_CATEGORIES':
return action.payload
case 'DELETE_A_TODO': {
const { id } = action.payload
const categoryIndex = state
.findIndex(category => category.todos.some(todo => todo.id === id))
return state.map((category, i) => i === categoryIndex
? {
...category,
todos: category.todos.filter(todo => todo.id !== id),
}
: category
)
}
default:
return state
}
}
现在,如果您将类别索引和ID一起返回,则无需遍历每个todos数组以找到ID
export const deleteTodo = (id: number, categoryIndex: number) => {
return {
type: 'DELETE_A_TODO',
payload: { id, categoryIndex }
}
}
const categoriesReducer = (state: Category[] = [], action: Action) => {
switch (action.type) {
case 'GET_ALL_CATEGORIES':
return action.payload
case 'DELETE_A_TODO': {
const { id, categoryIndex } = action.payload
return state.map((category, i) => i === categoryIndex
? {
...category,
todos: category.todos.filter(todo => todo.id !== id),
}
: category
)
}
default:
return state
}
}
答案 2 :(得分:1)
在您的DELETE情况下,调用forEach方法实际上不会返回新的数组,并且您也不会返回新的状态对象,因此会出现问题。
您需要映射状态并返回具有更新的todo数组的新类别对象。可以使用以下代码来实现:
case 'DELETE_A_TODO':
return state.map(category => {
return {
...category,
todos: category.todos.filter(
todo => todo.id !== action.payload.id
)
};
});
希望有帮助。