Разве Redux не является просто прославленным глобальным государством?

86

Так что я начал изучать React неделю назад и неизбежно столкнулся с проблемой состояния и того, как компоненты должны взаимодействовать с остальной частью приложения. Я поискал, и мне кажется, что Redux - это аромат месяца. Я прочитал всю документацию и считаю, что это действительно революционная идея. Вот мои мысли по этому поводу:

Состояние обычно считается довольно злым и большим источником ошибок в программировании. Вместо того, чтобы разбрасывать все это по всему вашему приложению, Redux говорит, почему бы просто не сконцентрировать все это в глобальном дереве состояний, для изменения которого вы должны генерировать действия? Звучит интересно. Все программы нуждаются в состоянии, поэтому давайте поместим его в одно нечистое пространство и изменим его только изнутри, чтобы ошибки можно было легко отслеживать. Затем мы также можем декларативно привязать отдельные части состояния к компонентам React и заставить их автоматически перерисовываться, и все будет красиво.

Однако у меня есть два вопроса обо всем этом дизайне. Во-первых, почему дерево состояний должно быть неизменным? Скажем, меня не волнует отладка путешествия во времени, горячая перезагрузка, и я уже реализовал отмену / повтор в моем приложении. Это кажется таким громоздким:

case COMPLETE_TODO:
  return [
    ...state.slice(0, action.index),
    Object.assign({}, state[action.index], {
      completed: true
    }),
    ...state.slice(action.index + 1)
  ];

Вместо этого:

case COMPLETE_TODO:
  state[action.index].completed = true;

Не говоря уже о том, что я делаю интерактивную доску просто для обучения, и каждое изменение состояния может быть таким же простым, как добавление мазка кисти в список команд. Через некоторое время (сотни мазков кисти) копирование всего этого массива может стать чрезвычайно дорогим и трудоемким.

Я согласен с глобальным деревом состояний, независимым от пользовательского интерфейса, который изменяется с помощью действий, но действительно ли оно должно быть неизменным? Что плохого в такой простой реализации (очень черновой вариант. Написан за 1 минуту)?

var store = { items: [] };

export function getState() {
  return store;
}

export function addTodo(text) {
  store.items.push({ "text": text, "completed", false});
}

export function completeTodo(index) {
  store.items[index].completed = true;
}

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

Райан Пешель
источник
2
«Во-первых, почему дерево состояний должно быть неизменным?» --- тогда вы должны предоставить алгоритм, чтобы определить, изменились ли данные. Невозможно реализовать его для произвольной структуры данных (если она изменяема). Взять immutablejsи использовать return state.setIn([action.index, 'completed'], true);для уменьшения шаблонного.
zerkms
1
PS:return state.map(i => i.index == action.index ? {...i, completed: true} : i);
zerkms

Ответы:

53

Разве Redux не является просто прославленным глобальным государством?

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

Неизменяемость позволяет очень эффективно проверять, было ли изменено какое-либо поддерево, потому что это упрощает проверку личности.

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

Если вы используете React, он в конечном итоге выполнит сравнение с фактическим dom и выполнит минимальные пакетно-оптимизированные манипуляции, но полный нисходящий повторный рендеринг по-прежнему неэффективен.

Для неизменяемого дерева компоненты без состояния просто должны проверить, отличаются ли поддерево (я), от которых они зависят, идентичностями от предыдущих значений, и если да, то рендеринга можно полностью избежать.

Lorefnon
источник
3
Но разве это не преждевременная оптимизация? Кроме того, как мы узнаем, что стоимость постоянного дублирования неизменяемых объектов меньше, чем повторный рендеринг DOM (также не сможет ли виртуальный DOM React сильно снизить эту стоимость?)
Райан Пешел
3
Ну, библиотеки GUI такого рода оптимизации уже давно (см. Bitquabit.com/post/the-more-things-change ) Плюс управление неизменяемой структурой данных не так дорого, как вы могли подумать - например, если узел изменяется, только одна цепочка родителей должна быть объединена в цепочку - остальные узлы остаются неизменными. Таким образом, мы не дублируем всю структуру данных для каждого действия - мы повторно используем подкомпоненты, которые не изменились, для создания новой структуры данных.
lorefnon
4
Также Reacts Virtual DOM - это не совсем темная магия. Цитата из документов React: «Создание минимального количества операций для преобразования одного дерева в другое - сложная и хорошо изученная проблема. Современные алгоритмы имеют сложность порядка of O (n3), где n - количество узлов в дереве »,
lorefnon
2
Причина, по которой React может работать намного лучше на практике, заключается в том, что: React полагается на эвристику - поэтому: «Если вы не предоставляете стабильные ключи (например, используя Math.random ()), все поддеревья будут каждый раз перерисовывать заново. Предоставляя пользователям возможность выбирать ключ, они получают возможность стрелять себе в ногу ». Точно так же, как вы можете помочь React, предоставляя стабильные ключи, точно так же вы можете помочь React, предоставляя неизменяемые свойства данных.
lorefnon,
1
Относительно вашего массива мазков кисти - пожалуйста, обратитесь: facebook.github.io/immutable-js/docs/#/List Цитата из документов: списки упорядочены, индексированные плотные коллекции, во многом как массив JavaScript. Списки реализуют Deque с эффективным добавлением и удалением как с конца (push, pop), так и с начала (unshift, shift).
lorefnon