Reducer 允许您合并组件的状态更新逻辑。上下文允许您将信息深入传递到其他组件。您可以将 reducer 和 context 组合在一起,以管理复杂屏幕的状态。
将减速器与上下文相结合
在 reducer 简介中的此示例中,状态由 reducer 管理。reducer 函数包含所有状态更新逻辑,并在以下文件底部声明:
import { useReducer } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; export default function TaskApp() { const [tasks, dispatch] = useReducer( tasksReducer, initialTasks ); function handleAddTask(text) { dispatch({ type: 'added', id: nextId++, text: text, }); } function handleChangeTask(task) { dispatch({ type: 'changed', task: task }); } function handleDeleteTask(taskId) { dispatch({ type: 'deleted', id: taskId }); } return ( <> <h1>Day off in Kyoto</h1> <AddTask onAddTask={handleAddTask} /> <TaskList tasks={tasks} onChangeTask={handleChangeTask} onDeleteTask={handleDeleteTask} /> </> ); } function tasksReducer(tasks, action) { switch (action.type) { case 'added': { return [...tasks, { id: action.id, text: action.text, done: false }]; } case 'changed': { return tasks.map(t => { if (t.id === action.task.id) { return action.task; } else { return t; } }); } case 'deleted': { return tasks.filter(t => t.id !== action.id); } default: { throw Error('Unknown action: ' + action.type); } } } let nextId = 3; const initialTasks = [ { id: 0, text: 'Philosopher’s Path', done: true }, { id: 1, text: 'Visit the temple', done: false }, { id: 2, text: 'Drink matcha', done: false } ];
import { useState } from 'react'; export default function AddTask({ onAddTask }) { const [text, setText] = useState(''); return ( <> <input placeholder="Add task" value={text} onChange={e => setText(e.target.value)} /> <button onClick={() => { setText(''); onAddTask(text); }}>Add</button> </> ) }
import { useState } from 'react'; export default function TaskList({ tasks, onChangeTask, onDeleteTask }) { return ( <ul> {tasks.map(task => ( <li key={task.id}> <Task task={task} onChange={onChangeTask} onDelete={onDeleteTask} /> </li> ))} </ul> ); } function Task({ task, onChange, onDelete }) { const [isEditing, setIsEditing] = useState(false); let taskContent; if (isEditing) { taskContent = ( <> <input value={task.text} onChange={e => { onChange({ ...task, text: e.target.value }); }} /> <button onClick={() => setIsEditing(false)}> Save </button> </> ); } else { taskContent = ( <> {task.text} <button onClick={() => setIsEditing(true)}> Edit </button> </> ); } return ( <label> <input type="checkbox" checked={task.done} onChange={e => { onChange({ ...task, done: e.target.checked }); }} /> {taskContent} <button onClick={() => onDelete(task.id)}> Delete </button> </label> ); }
reducer 有助于使事件处理程序保持简短。但是,随着应用的增长,您可能会遇到另一个困难。目前,任务
状态和调度
功能仅在顶级 TaskApp
组件中可用。若要让其他组件读取任务列表或更改它,必须显式传递当前状态和更改它的事件处理程序作为道具。
例如,将任务列表和事件处理程序传递给:TaskApp
TaskList
<TaskList tasks={tasks} onChangeTask={handleChangeTask} onDeleteTask={handleDeleteTask} />
并将事件处理程序传递给:TaskList
Task
<Task task={task} onChange={onChangeTask} onDelete={onDeleteTask} />
在像这样的小例子中,这很有效,但是如果你中间有几十个或几百个组件,那么传递所有状态和函数可能会非常令人沮丧!