@Whuthering

Почему в Redux редьюсеры должны быть чистыми функциями?

Разбираюсь в Redux и Vuex, и возник такой вот вопрос.
В Redux редьюсер обязательно должен быть pure function. На вход редьюсера мы подаем какой-то объект-состояние, а на выходе он должен нам создать новый объект с нужными изменениями.
При этом Vuex для аналогичной задачи прекрасно живет без такого требования, и более того, там даже принято явно мутировать существующее состояние.
В чем плюсы pure functions мне вполне понятно, но только в случае с чистым функциональным программированием, в котором в принципе отсутствует какое-то состояние. А в случае с Redux у нас, наоборот, существует глобальное состояние, на которое всё и завязано. Поэтому всплывает вопрос "Зачем?".
Для удобства тестирования? Мол, легко подать что-то на вход функции, а потом проверить, что на выходе получилось то, что ожидалось? С тем же успехом можно можно использовать функции, явно изменяющие переданное им состояние без создания нового. Сделать глубокую копию до теста, и сравнить с тем, что получилось после теста. Значит, дело не в этом.
Для удобства версионирования (снэпшоты, и т.д.) состояния? Аналогично, при необходимости можно просто делать deep copy старого состояния, перед вызовом редьюсера, сделав обертку для него. Что в том, что в другом случае, у нас будет копироваться объект и его члены.
Для отсутствия побочных эффектов? Программист, если сильно захочет, в коде редьюсера сможет добавить "от себя" что-то в общее состояние, и таким образом у нас опять же добавится еще состояние функции-редьюсера, что есть прямой путь к побочным эффектам. А Javascript так вообще не запрещает еще потыкать какие-нибудь другие глобальные объекты из кода функции. Так что тут вопрос не сколько в "чистых функциях", сколько в дисциплине и культуре разработчика.
Для уменьшения необходимости сравнить, изменилось ли что-нибудь в состоянии после работы редьюсера? Типа, если ничего не изменилось, то мы возвращаем тот же самый объект состояния, и код, вызвавший редьюсер, понимает, что ничего делать не надо? Как по мне, чаще все-таки что-то меняется, чем не меняется, и в любом случае сравнивать изменения членов состояния потом придется в любом случае, когда настанет время решать, какие компоненты нужно пере-рендерить.
Так зачем?
  • Вопрос задан
  • 132 просмотра
Решения вопроса 1
Для уменьшения необходимости сравнить, изменилось ли что-нибудь в состоянии после работы редьюсера? Типа, если ничего не изменилось, то мы возвращаем тот же самый объект состояния, и код, вызвавший редьюсер, понимает, что ничего делать не надо?
Это главная причина, но и всё остальное, что вы перечислили, тоже важно.

Как по мне, чаще все-таки что-то меняется, чем не меняется, и в любом случае сравнивать изменения членов состояния потом придется в любом случае, когда настанет время решать, какие компоненты нужно пере-рендерить.
Во-первых, такое сравнение будет дешёвым, поскольку происходит оно на уровне ссылок.
Во-вторых, изменения в приложении обычно локальные и если у вас изменилось что-то в одной части приложения, другие не изменятся и не будут перерендерены.

Вдобавок, это хорошо согласуется с философией Реакта, где каждый рэндер - это тоже чистая функция.

Ещё в redux-мире популярен time-travel и replay экшенов - при недетерминированных редьюсерах эти фичи работать не будут.

Но раз вы накатали такую простыню с аргументами и они вас не убедили, то и мои, скорее всего, не убедят, поэтому итоговый ответ простой - так захотел Дэн Абрамов. Ему перечисленных вами плюсов показалось достаточно.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
от 80 000 до 115 000 руб.
meyvn Санкт-Петербург
от 160 000 руб.
Playneta Санкт-Петербург
от 120 000 до 150 000 руб.