Конечно, он его не изобретал. Но если бы посмотрел сегодня сливы собесов, точно увидел бы в них свои идеи. Ведь есть же фундаментальные идеи за всей этой шелухой про синтаксис mapStateToProps!

Тьюринг думает надо логотипом Redux
Тьюринг думает надо логотипом Redux

Императивное программирование

Допустим, вам поручили сделать web проигрыватель. Бизнес ставит задачи, сроки горят. Что делаем? Правильно, берём родной <audio>.

<audio src="https://cdn.pixabay.com/audio/2025/03/18/audio_7d5c12b31a.mp3"></audio>

Нужно будет лишь подписаться на его события.

// Обработчики событий элемента <audio>

audio.addEventListener("play", () => {
  // ...
});

audio.addEventListener("pause", () => {
  // ...
});

audio.addEventListener("ended", () => {
  // ...
});

// Обновление прогресса
audio.addEventListener("timeupdate", () => {
  // ...
});

Самое интуитивное желание — определить четыре флага для каждого возможного состояния проигрывателя. 

// Множество флагов состояния
var isPlaying = false;
var isPaused = false;
var isStopped = false;
var isEnded = false;

И на каждое событие проверить все флаги и выключить логически ненужные. В конце - перерисовать интерфейс. 

audio.addEventListener("play", () => {
  isPlaying = true;
  isPaused = false;
  isStopped = false;
  isEnded = false;

  updateUI();
});

Всё работает! Что ещё можно желать?

Ссылка на рабочий пример: https://jsbin.com/huyijutoyi/edit?js,output

Автоматное программирование

Проблема с флагами в их необязательности. Может ли проигрыватель быть одновременно в isPlaying и isEnded? По логике — нет, но в коде ничто не мешает этому случиться. 

В командной разработке нужно решение, которое сделает такие ошибки невозможными. Решение, которое облегчит жизнь не только программистам, но и бизнесу. И оно было придумано задолго до JavaScript — это конечные автоматы. Заметный вклад в объединение этой темы с программированием внёс Алан Тьюринг. 

Вернёмся в воображаемую контору. Вот планы команды на ближайшее будущее:

  • Записывать действия пользователей

  • Поддерживать состояния: volumechange, waiting, emptied 

  • Прислушаться к советам мудрого сторожилы конторы и использовать «design patterns» для разбиения на файлы

И всего через три итерации уже ясно, что следующая задача — документирование количества флагов и мест, где они могут меняться. 

Нужно решение! Чтобы большая команда делала меньше ошибок. 

Да и чтобы бизнес понимал какие состояния бывают и что умеет приложение.

Немного поискав информацию, можно найти прекрасные доклады и целую книгу:

Решено! Будем использовать наследие Алана Тьюринга и его современников - использовать конечные автоматы. 

Конечные автоматы

Посмотрим на схему работы, может что-то можно переписать иначе?

Три флага состояний
Три флага состояний

Нужно не улучшить текущий код, а переписать его заново (да, тоже нужно будет протолкнуть на планировании)!

Буквально, поменять эти флаги на состояние. Написать простую схему переходов между ними и запрограммировать с функцией-редуктором. 

Граф состояний
Граф состояний

Благо, в воображаемом примере не всё так плохо. Можно легко переписать флаги на множество управляющих состояний. 

// Множество управляющих состояний
var STATES = {
  STOPPED: "⏹️ Остановлен",
  PLAYING: "? Играет",
  PAUSED: "⏸️ Пауза",
  ENDED: "✅ Завершено",
};

А бизнес-логику приложения перенести из каждого события в функцию переходов (она же редуктор). 

// Функция переходов
function handleAction(action) {
  switch (action) {
    case "PLAY":
      if (currentState === STATES.STOPPED || currentState === STATES.PAUSED) {
        audio.play();
        currentState = STATES.PLAYING;
      }
      break;

    case "PAUSE":
      // ...
      break;

    case "STOP":
      // ...
      break;
  }

  updateUI();
}

Обновление интерфейса теперь простая задача: есть состояние - покажи сообщение. 

И так мы переехали на автоматное программирование!

  1. У нас есть единое управляющее состояние

  2. Логика переходов единственно, полно и декларативно описана в функции переходов

  3. Этот switch-case уже можно вынести в отдельную библиотеку!

Ссылка на рабочий пример: https://jsbin.com/kelukazovu/edit?js,output.

Redux

Так и сделаем! А потом, а потом…

  • Сделаем независимую от бизнес-логики библиотеку,

  • чтобы и в реакте работало,

  • чтобы и обновление частей состояния не вызывало перерисовки!!

  • Чтобы были плагины в браузере для истории переходов!

Постойте... нам что, нужен Redux?!

Конечно, для нашего такого проигрывателя — это стрельба из базуки по воробьям. Но главное – это фундаментальный принцип, на котором он построен. 

Redux — это не просто магический и новомодный синтаксис с экосистемой. Это, в первую очередь, реализация архитектурного шаблона конечного автомата, дополненная удобными инструментами (middleware, dev-tools).

Ссылка на рабочий пример с Redux: https://jsbin.com/wazimaziga/edit?js,output

Вывод

Так я показал проблему управления состоянием и её решения, начав аж с самого Тьюринга!

Я жалею, что никто не рассказывал мне про redux именно так. Большинство блогеров сразу переходят к синтаксису, не отвечая на вопрос: “оно вообще зачем нужно?”.

Так же я ранее рассмотрел и тему замыканий, начав с проблемы фунарга. И ещё много говорил про концепции React

Если вы есть, будьте первыми!

Комментарии (5)


  1. Tzimie
    13.11.2025 08:55

    Надо было начать с Рюрика


    1. Alexandroppolus
      13.11.2025 08:55

      Редукс существовал задолго до Рюрика, просто ещё не был открыт


      1. gev
        13.11.2025 08:55

        Еще в Древнем Риме! И уже потом его не Тьюринг, а Чёрч перепридумал для лямбда-исчисления!


      1. Tzimie
        13.11.2025 08:55

        Месье Платонист? Жму руку


  1. Arhammon
    13.11.2025 08:55

    Вроде блок-схемы придумали для удобного восприятия процессов, а не для дизайнерских изысков...