react 使用 Reducer 和 Context 进行纵向扩展

简介: react 使用 Reducer 和 Context 进行纵向扩展

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 组件中可用。若要让其他组件读取任务列表或更改它,必须显式传递当前状态和更改它的事件处理程序作为道具。

例如,将任务列表和事件处理程序传递给:TaskAppTaskList

<TaskList
tasks={tasks}
onChangeTask={handleChangeTask}
onDeleteTask={handleDeleteTask}
/>


并将事件处理程序传递给:TaskListTask

<Task
task={task}
onChange={onChangeTask}
onDelete={onDeleteTask}
/>


在像这样的小例子中,这很有效,但是如果你中间有几十个或几百个组件,那么传递所有状态和函数可能会非常令人沮丧!

相关文章
|
1月前
|
前端开发 API
React 之 Context 的变迁与背后实现
React 之 Context 的变迁与背后实现
34 0
|
1月前
|
前端开发 JavaScript API
React的Context API:全局状态管理的利器
【4月更文挑战第25天】React的Context API解决了深层组件间状态共享的难题,提供全局状态管理方案。通过`Provider`和`Consumer`组件,或结合`useContext` Hook,实现状态在组件树中的传递。最佳实践包括避免过度使用,分离逻辑,以及在必要时与Redux或MobX结合。Context API简化了数据传递,但需谨慎使用以保持代码清晰。
|
1月前
|
前端开发
深入理解 React 中的 Context
深入理解 React 中的 Context
|
1月前
|
前端开发
深入理解 React 中的 Context(二)useContext、createContext
深入理解 React 中的 Context(二)useContext、createContext
|
1月前
|
存储 前端开发 JavaScript
【思维扩展】状态机与 React 中的状态
【思维扩展】状态机与 React 中的状态
|
1月前
|
存储 JavaScript 开发者
Mobx+Mobx-React快速上手 简单可扩展的状态管理解决方案
Mobx+Mobx-React快速上手 简单可扩展的状态管理解决方案
38 0
|
1月前
|
前端开发
React中兄弟组件通信和组件跨级传递Context的使用
React中兄弟组件通信和组件跨级传递Context的使用
|
1月前
|
前端开发
react的context状态树怎么使用
react的context状态树怎么使用
35 0
|
1月前
|
缓存 前端开发
react扩展
react扩展
58 0
|
8月前
|
JavaScript 前端开发 容器
React-跨组件通讯-context
React-跨组件通讯-context
35 0