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

Императивное программирование
Допустим, вам поручили сделать 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» для разбиения на файлы
И всего через три итерации уже ясно, что следующая задача — документирование количества флагов и мест, где они могут меняться.
Нужно решение! Чтобы большая команда делала меньше ошибок.
Да и чтобы бизнес понимал какие состояния бывают и что умеет приложение.
Немного поискав информацию, можно найти прекрасные доклады и целую книгу:
Кирилл Мокевнин, Конечные автоматы как способ значительно упростить логику и понимание кода
"Автоматное программирование" Поликарпова Н. И., Шалыто А. А.
Александр Усков — Автоматное программирование и его применение в видеостриминге
Конечный автомат на React Hooks и Typescript — Сергей Володин
Решено! Будем использовать наследие Алана Тьюринга и его современников - использовать конечные автоматы.
Конечные автоматы
Посмотрим на схему работы, может что-то можно переписать иначе?

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

Благо, в воображаемом примере не всё так плохо. Можно легко переписать флаги на множество управляющих состояний.
// Множество управляющих состояний
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();
}
Обновление интерфейса теперь простая задача: есть состояние - покажи сообщение.
И так мы переехали на автоматное программирование!
У нас есть единое управляющее состояние
Логика переходов единственно, полно и декларативно описана в функции переходов
Этот 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.
Если вы есть, будьте первыми!
Комментарии (12)

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

nihil-pro
13.11.2025 08:55А бизнес-логику приложения перенести из каждого события в функцию переходов (она же редуктор).
А можно не выдумывать сложности там где их нет, и не пытаться оправдать существование редакса, с его уродским синтаксисом, тем, что якобы мы, решая некую там задачу – к нему же и придем.
const handler = { currentState: undefined; handleEvent(event) { this.currentState = event.type; switch (event.type) { case "play": // ... break; case "pause": // ... break; case "ended": // ... break; case "timeupdate": // ... break; case default; // ... } } } // audio = HTMLAudioElement audio.addEventListener(handler); // later audio.removeEventListener(handler);Какой практический смысл в том, что вы преобразовали
play,pause,endedиtimeupdateвPLAYING,STOPPED,PAUSEDиENDED?Сделаем независимую от бизнес-логики библиотеку,
Что вам это дало?
чтобы и в реакте работало,
А если Vue? Angular? Solid?
чтобы и обновление частей состояния не вызывало перерисовки!!
Значит ли это, что при обновлении части состояния, например с PLAYING на PAUSED, пользователь это не увидет?
Чтобы были плагины в браузере для истории переходов!
Чтобы что? Для чего? Да, мы знаем, что редакс подает как мегафишку то, что вообще говоря почти никогда не требуется, а если требуется, то очень легко реализуется и без него?

AlekseiVolkov Автор
13.11.2025 08:55Отличный вопрос!
А можно не выдумывать сложности там где их нет
100% можно. Это лишь пример, именно в нём конечно не нужен редакс. Но и ваш пример как раз про автоматное программирование - переход от событийной логики в конечному автомату.
Редакс это просто реализация такого подхода в реакте. Чтобы не всё приложение перерисовывалось и прочие плюшки.Что вам это дало?
А если Vue? Angular? Solid?
Это пример будущих мыслей бизнеса и техлидов.
Значит ли это, что при обновлении части состояния, например с PLAYING на PAUSED, пользователь это не увидет?
В реакте можем использовать редакс* в корне и он не будет вызывать перерисовок всего приложения.
* – redux + react-redux
Чтобы что? Для чего? Да, мы знаем, что редакс подает как мегафишку то, что вообще говоря почти никогда не требуется, а если требуется, то очень легко реализуется и без него?
Чисто для отладки. Чтобы не console.log писать (даже через debugger), а видеть как менялось состояние. А как без редакса смотреть и менять состояние вашего примера handleEvent?

adminNiochen
13.11.2025 08:55Не знаю кто писал эту статью, но живые программисты не говорят "редуктор"

Egor_Grin
13.11.2025 08:55какое счастье, что на первой работе, я попал в команду с тимлидом - джавистом, выбравшим для фронта Ангуляр...

dominus_augustus
13.11.2025 08:55Оказаться на проекте с редаксом - это боль
Выбрать редакс целеноправленно - это диагноз

AgentGenerous
13.11.2025 08:55"Редукторы" это вещь! ...от которых мы сейчас всеми силами избавляемся и переходим на ванильный TS, именно как написал @nihil-pro
Tzimie
Надо было начать с Рюрика
Alexandroppolus
Редукс существовал задолго до Рюрика, просто ещё не был открыт
gev
Еще в Древнем Риме! И уже потом его не Тьюринг, а Чёрч перепридумал для лямбда-исчисления!
Tzimie
Месье Платонист? Жму руку