> Как различать и отличать action в Redux? (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Инрэко

Стек: JavaScript

> Пример ответа

Короткий ответ

Action в Redux - это плоский объект с обязательным полем type (строковая константа, уникально идентифицирующая намерение) и необязательным полем payload для данных. Различать action нужно по type, а отличать - по структуре и семантике: каждый action описывает одно конкретное событие или намерение, а не несколько. Для удобства типы выносят в константы, а создание action - в action creators.

Подробное объяснение

Action - это единственный источник информации для store в Redux. Он описывает факт, который произошёл в приложении, но не содержит логики изменения состояния. Различать action означает:

  1. По type - это строка, которая должна быть уникальной в рамках всего приложения. Обычно используется формат 'domain/eventName', например 'todos/addTodo'. Это позволяет избежать коллизий и упрощает отладку.

  2. По структуре - кроме type, action может содержать payload (данные), meta (дополнительная информация, не влияющая на состояние) и error (флаг для ошибок). Стандарт Flux Standard Action (FSA) рекомендует именно такую структуру.

  3. По семантике - action должен отвечать на вопрос "что произошло?", а не "как обновить состояние?". Например, 'user/loginSuccess' лучше, чем 'user/setIsLoggedIn'.

Отличать action от похожих сущностей:

  • От action creator - это функция, которая возвращает action. Она инкапсулирует создание объекта и позволяет переиспользовать логику.
  • От reducer - reducer обрабатывает action и возвращает новое состояние, но сам action не содержит логики.
  • От middleware - middleware перехватывает action до reducer, может его модифицировать, отменять или вызывать побочные эффекты.

На практике

На уровне senior важно не просто знать определение, а уметь проектировать систему action так, чтобы она была масштабируемой и предсказуемой. Ключевые практики:

  • Типизация - в TypeScript action описывается как discriminated union по полю type. Это даёт автодополнение и проверку типов в reducer и middleware.
  • Константы типов - выносить в отдельный файл или использовать as const в TypeScript. Это предотвращает опечатки и упрощает рефакторинг.
  • Action creators - всегда использовать функции, даже для простых action. Это позволяет добавить логику позже без изменения вызывающего кода.
  • Нормализация - не смешивать несколько намерений в одном action. Если нужно обновить несколько сущностей, лучше отправить несколько action или использовать один action с чёткой структурой payload.
  • Сериализуемость - action должен быть сериализуемым (без функций, Promise, классов). Это требование для time-travel debugging и persistence.

Пример кода

JAVASCRIPT
// Типы action как константы
export const ADD_TODO = 'todos/addTodo';
export const TOGGLE_TODO = 'todos/toggleTodo';
export const FETCH_TODOS_SUCCESS = 'todos/fetchTodosSuccess';
// Action creators
export const addTodo = (text) => ({
type: ADD_TODO,
payload: { id: Date.now(), text, completed: false },
});
export const toggleTodo = (id) => ({
type: TOGGLE_TODO,
payload: { id },
});
export const fetchTodosSuccess = (todos) => ({
type: FETCH_TODOS_SUCCESS,
payload: todos,
});
// Пример с TypeScript - discriminated union
type TodoAction =
| { type: typeof ADD_TODO; payload: { id: number; text: string; completed: boolean } }
| { type: typeof TOGGLE_TODO; payload: { id: number } }
| { type: typeof FETCH_TODOS_SUCCESS; payload: Todo[] };

Как отвечать на собеседовании

Начните с формального определения, затем переходите к практическим аспектам. Подчеркните, что различать action - это про type, а отличать - про структуру и семантику. Приведите пример из реального проекта: как вы проектировали action для сложного сценария (например, загрузка данных с сервера). Упомяните, что в современном Redux Toolkit используется createAction и createSlice, которые автоматически генерируют action creators и типы, но понимание базовой механики остаётся обязательным. Если спросят про альтернативы - скажите, что action можно заменить на события в других стейт-менеджерах, но в Redux это фундаментальная концепция.

Что проверяет интервьюер

Интервьюер оценивает:

  • Понимание базовой модели Redux: однонаправленный поток данных, чистота action.
  • Умение проектировать action для реальных задач, а не только заученные определения.
  • Знание практик: константы, action creators, типизация, FSA.
  • Способность объяснить trade-off между "одним action на много изменений" и "многими action".
  • Понимание роли middleware и того, как action проходит через него.

Типичные ошибки

  • Смешение action и action creator - говорят "action - это функция", хотя это объект.
  • Неуникальные type - используют 'ADD' вместо 'todos/add', что приводит к конфликтам в больших приложениях.
  • Слишком общие или слишком конкретные action - например, 'updateData' вместо 'user/updateProfile'.
  • Несериализуемый payload - кладут функции или классы в action, что ломает devtools и middleware.
  • Императивные названия - 'setLoadingTrue' вместо 'fetchStarted'. Action должен описывать событие, а не команду.
  • Игнорирование FSA - используют произвольные поля вместо payload, что усложняет отладку и типизацию.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью