Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як поєднати useReducer і Context для стану частини застосунку?

Для стану, яким користуються компоненти на різних рівнях дерева (кошик, список завдань, налаштування), React пропонує поєднання useReducer + Context без сторонніх бібліотек.

const TasksContext = createContext(null);
const TasksDispatchContext = createContext(null);

export function TasksProvider({ children }) {
  const [tasks, dispatch] = useReducer(tasksReducer, []);

  return (
    <TasksContext value={tasks}>
      <TasksDispatchContext value={dispatch}>
        {children}
      </TasksDispatchContext>
    </TasksContext>
  );
}

export function useTasks() {
  const tasks = useContext(TasksContext);
  if (tasks === null) throw new Error('useTasks має бути всередині TasksProvider');
  return tasks;
}

export function useTasksDispatch() {
  return useContext(TasksDispatchContext);
}

У React 19 сам контекст можна рендерити як провайдер (<TasksContext value={...}>); старий запис <TasksContext.Provider> теж працює.

Використання в будь-якому компоненті під провайдером:

function AddTask() {
  const dispatch = useTasksDispatch();
  return <button onClick={() => dispatch({ type: 'added', text: 'Нове завдання' })}>Додати</button>;
}

function TaskList() {
  const tasks = useTasks();
  return tasks.map((task) => <Task key={task.id} task={task} />);
}

Чому два контексти, а не один:

  • dispatch стабільний - не змінюється між рендерами;
  • компоненти, яким потрібна лише відправка дій (кнопки, форми), підписуються лише на TasksDispatchContext і не перерендерюються, коли змінюється список завдань.

Переваги підходу:

  • логіка змін - в одному редукторі, її легко тестувати;
  • компоненти не передають колбеки через десятки рівнів;
  • власні хуки (useTasks) приховують деталі й перевіряють наявність провайдера.

Обмеження, через які переходять на сховища:

  • будь-яка зміна значення контексту перерендерює всіх його споживачів - навіть тих, кому потрібна лише частина даних. Немає селекторів «підпишись лише на це поле»;
  • провайдери, що вкладаються один в один для кожної частини стану, ускладнюють структуру;
  • немає інструментів налагодження «з коробки», проміжних обробників (middleware), збереження стану.

Для частих оновлень і великого спільного стану - Zustand, Redux Toolkit чи подібні з підписками на частину стану.

Докладніше в документації: Масштабування з reducer і context

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання