我正试图习惯于对钩子useReduce
做出反应,为此,我正在制作一个todoList
示例,其中我想使用一个reduce来管理诸如添加,编辑,更新,删除和更改任务的完成状态,并在另一个reduce管理过滤器中,该过滤器使我可以列出所有todos
或仅列出已完成和未完成。
是否可以使用useReducer钩子通过多个减少器管理状态?
现在,我不得不混合使用减速器,其逻辑如下
import React, { useReducer, useState } from "react";
import uuid from "uuid/v4";
import Form from "../Form/Form";
import List from "../List/List";
import Filter from "../Filter/Filter";
const todoReducer = (state, action) => {
switch (action.type) {
case "ADD_TODO":
return applyAddTodo(state, action);
case "DELETE_TODO":
return applyDeleteTodo(state, action);
case "EDIT_TODO":
return applyEditTodo(state, action);
case "CANCEL_EDIT_TODO":
return applyCancelEditTodo(state, action);
case "UPDATE_TODO":
return applyUpdateTodo(state, action);
case "TOGGLE_COMPLETED_TODO":
return applyToggleCompletedTodo(state, action);
case "COMPLETED": // <- from here this should be in another reducer
return applyFilterCompleted(state);
case "UN_COMPLETED":
return applyFilterUncompleted(state);
case "ALL":
default:
return [...state];
}
};
const todoFilter = (state, action) => {
switch (action.type) {
case "COMPLETED":
return applyFilterCompleted(state, action);
case "UN_COMPLETED":
return applyFilterUncompleted(state, action);
case "ALL":
default:
return [...state];
}
};
const applyAddTodo = (state, action) => [
...state,
{ id: uuid(), task: action.payload.task, completed: false, isEditing: false }
];
const applyDeleteTodo = (state, action) =>
state.filter(todo => todo.id !== action.payload.id);
const applyEditTodo = (state, action) =>
state.map(todo =>
todo.id === action.payload.id ? { ...todo, isEditing: true } : { ...todo }
);
const applyCancelEditTodo = (state, action) =>
state.map(todo =>
todo.id === action.payload.id ? { ...todo, isEditing: false } : { ...todo }
);
const applyUpdateTodo = (state, action) =>
state.map(todo =>
todo.id === action.payload.id
? { ...todo, task: action.payload.task, isEditing: false }
: { ...todo }
);
const applyToggleCompletedTodo = (state, action) =>
state.map(todo =>
todo.id === action.payload.id
? { ...todo, completed: !todo.completed }
: { ...todo }
);
const applyFilterCompleted = state => state.filter(todo => todo.completed);
const applyFilterUncompleted = state => state.filter(todo => !todo.completed);
const INITIAL_STATE = [
{
id: uuid(),
task: "Learn react",
dateCreated: Date.now(),
completed: false,
isEditing: false
},
{
id: uuid(),
task: "Learn react hooks",
dateCreated: Date.now(),
completed: true,
isEditing: false
}
];
const App = () => {
const [state, dispatch] = useReducer(todoReducer, INITIAL_STATE);
const [filter, setFilter] = useState("ALL");
const addTodoHandler = task =>
dispatch({ type: "ADD_TODO", payload: { task } });
const editTodoHandler = id =>
dispatch({ type: "EDIT_TODO", payload: { id } });
const updateTodoHandler = (id, task) =>
dispatch({ type: "UPDATE_TODO", payload: { id, task } });
const cancelEditTodoHandler = id =>
dispatch({ type: "CANCEL_EDIT_TODO", payload: { id } });
const deleteTodoHandler = id =>
dispatch({ type: "DELETE_TODO", payload: { id } });
const toggleCompletedTodoHandler = id =>
dispatch({ type: "TOGGLE_COMPLETED_TODO", payload: { id } });
const filterHandler = filter => setFilter(filter);
return (
<div>
<Form onAddTodo={addTodoHandler} />
{state.length > 0 && (
<div>
<List
todos={todoFilter(state, { type: filter })}
onEditTodo={editTodoHandler}
onUpdateTodo={updateTodoHandler}
onCancelEditTodo={cancelEditTodoHandler}
onDeleteTodo={deleteTodoHandler}
onToggleCompletedTodo={toggleCompletedTodoHandler}
/>
<Filter onFilter={filterHandler} />
</div>
)}
</div>
);
};
export default App;
现在,约简todoFilter
我将其用作列出todos
的助手
更新1
我有这个解决方案
Todo减速器
const todoReducer = (state, action) => {
switch (action.type) {
case "ADD_TODO":
return applyAddTodo(state, action);
case "DELETE_TODO":
return applyDeleteTodo(state, action);
case "EDIT_TODO":
return applyEditTodo(state, action);
case "CANCEL_EDIT_TODO":
return applyCancelEditTodo(state, action);
case "UPDATE_TODO":
return applyUpdateTodo(state, action);
case "TOGGLE_COMPLETED_TODO":
return applyToggleCompletedTodo(state, action);
default:
return state;
}
};
过滤器减速器
const filterReducer = (state, action) => {
switch (action.type) {
case "COMPLETED":
return applyFilterCompleted(state, action);
case "UN_COMPLETED":
return applyFilterUncompleted(state, action);
case "ALL":
default:
return [...state];
}
};
主减速器
const reducer = (state, action) => {
switch (action.type) {
case "ADD_TODO":
case "DELETE_TODO":
case "EDIT_TODO":
case "UPDATE_TODO":
case "CANCEL_EDIT_TODO":
case "TOGGLE_COMPLETED_TODO":
return todoReducer(state, action);
case "COMPLETED":
case "UN_COMPLETED":
case "ALL":
return filterReducer(state, action);
default:
throw new Error();
}
};
这行得通,但是我不喜欢它,因为必须在主减速器和次减速器中重复动作类型,最终某些动作类型将被省略,应用程序将失败。
有没有更聪明的解决方案?
感谢您的评论