React-Redux: если все состояния компонентов должны храниться в Redux Store

89

Скажем, у меня есть простой переключатель:

Когда я нажимаю кнопку, цветовой компонент меняется с красного на синий.

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

index.js

Button: onClick={()=>{dispatch(changeColor())}}
Color: this.props.color ? blue : red

container.js

connect(mapStateToProps)(indexPage)

action_creator.js

function changeColor(){
 return {type: 'CHANGE_COLOR'}
}

reducer.js

switch(){
case 'CHANGE_COLOR':
return {color: true}

но это чертовски много кода для того, что я мог бы достичь за 5 секунд с помощью jQuery, некоторых классов и некоторых css ...

Итак, я думаю, что я действительно спрашиваю, что я здесь делаю не так?

l2silver
источник
6
response-redux не продается как нечто более короткое, чем jquery. Ему определенно нужен код, чтобы запустить его.
zerkms
1
Взгляните сюда: github.com/rackt/redux/issues/1287 , по этой теме много хороших дискуссий.
m0meni
1
спасибо @ AR7, отлично
l2silver
1
@ l2silver без проблем. По сути, идея состоит в том, что если цвет этого компонента не имеет значения для кого-либо еще, просто сохраните это состояние внутри самого компонента.
m0meni
2
упомянутая проблема AR7 перемещена: github.com/reactjs/redux/issues/1287
ptim

Ответы:

157

Redux в первую очередь предназначен для «состояния приложения». То есть все, что связано с логикой вашего приложения. Представление, построенное поверх него, является отражением этого состояния, но оно не обязательно должно использовать исключительно этот контейнер состояния для всего, что он делает.

Просто задайте следующие вопросы: важно ли это состояние для остальной части приложения? Будут ли другие части приложения вести себя по-другому в зависимости от этого состояния? Во многих незначительных случаях это не так. Возьмите раскрывающееся меню: тот факт, что оно открыто или закрыто, вероятно, не повлияет на другие части приложения. Так что подключить его к вашему магазину, вероятно, будет излишним. Это, безусловно, допустимый вариант, но на самом деле не приносит вам никаких преимуществ. Вам лучше использовать this.stateи закончить день.

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

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

Тим Дорр
источник
Эй, я знаю, что на этот вопрос никогда не будет однозначного ответа, но я думаю, что ваша логика здесь очень
здрава
3
Честно говоря, я вообще не понимаю, какой смысл использовать эту штуку flux / redux. В чем была проблема с моделью, управляемой событиями?
jayarjo
ИМО, это не идеальный ответ. Это зависит. Сохранение состояния ui в состоянии реакции сделает хранилище redux чистым, но в конечном итоге станет нефункциональным компонентом, который сложно протестировать. Сохранение состояния ui в состоянии реакции добавит много усилий разработчикам, потому что нам придется писать дополнительные редукторы. Тем не менее, существует множество пакетов, которые помогут вам упростить состояние вашего пользовательского интерфейса в хранилище redux, для получения дополнительных сведений см. Redux.js.org/docs/faq/OrganizingState.html .
Рон
19

Redux FAQ: Организация State
этой части официального документа redux хорошо ответила на ваш вопрос.

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

Некоторые общие практические правила для определения того, какие данные следует помещать в Redux:

  • Остальные части приложения заботятся об этих данных?
  • Вам нужно иметь возможность создавать дополнительные производные данные на основе этих исходных данных?
  • Используются ли одни и те же данные для управления несколькими компонентами?
  • Есть ли для вас ценность в возможности восстановить это состояние до заданного момента времени (например, отладка путешествия во времени)?
  • Вы хотите кэшировать данные (т. Е. Использовать то, что находится в состоянии, если оно уже есть, вместо повторного запроса)?
chuck911
источник
6

Чтобы выделить отличную ссылку, предоставленную @ AR7, и потому, что эта ссылка переместилась на некоторое время назад:

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

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

Практическое правило: делайте то, что менее неудобно.

Дэн Абрамов: https://github.com/reactjs/redux/issues/1287#issuecomment-175351978

птим
источник
-8

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

Каждый раз, когда вы не сохраняете изменение состояния компонента в Redux, это изменение полностью теряется из стека изменений Redux, и пользовательский интерфейс вашего приложения не будет синхронизироваться с хранилищем. Если для вас это не важно, спросите себя, зачем вообще использовать Redux? Без него ваше приложение будет менее сложным!

Из соображений производительности вы можете захотеть вернуться к this.setState()чему-либо, что могло бы многократно отправлять множество действий. Например: сохранение состояния поля ввода в Redux каждый раз, когда пользователь вводит ключ, может привести к снижению производительности. Вы можете решить эту проблему, рассматривая это как транзакцию: после того, как действие пользователя "зафиксировано", сохраните конечное состояние в Redux.

В вашем исходном посте упоминается, что способ Redux - это «чертовски много кода, который нужно писать». Да, но вы можете использовать абстракции для общих шаблонов, таких как состояние локального компонента.

kumar303
источник
Улучшенная отладка - полезная цель и приятная функция redux, но я думаю, что соотношение сигнал / шум также важно. Можно было бы регистрировать каждую переменную в базе кода, но это добавило бы много дополнительного кода, что затруднило бы чтение фактического кода, и регистрацию было бы трудно отслеживать. Я думаю, что то же самое относится и к использованию redux. Наличие всего состояния в redux может улучшить отладку, но есть затраты на дополнительный код и абстракции, которые могут затруднить чтение кода и даже усложнить некоторые задачи отладки. (И когда происходит сбой инструментов redux dev, многие достижения отладки теряются.)
Джей Ди Сандифер
1
Тогда зачем вообще использовать Redux? Если вы не поместите все в Redux, вы потеряете все функции, такие как инструменты разработчика. Это действительно все или ничего. Если вы используете setState () для раскрывающегося меню, как в верхнем ответе на этот пост, вы не можете использовать инструменты разработчика для отладки любых проблем, с которыми ваши пользователи могут столкнуться в раскрывающемся меню. Хуже, когда вы используете setState () для наложения, потому что нет возможности путешествовать во времени до и после показа наложения. Использование setState () здесь и там очень чревато ошибками, потому что разработчик должен постоянно думать о том, что может сломаться.
kumar303
В качестве более конкретного ответа, ведение журнала каждой переменной в базе кода не является полезной метафорой, поскольку вопрос заключается в том, использовать ли this.setState()или dispatch(action...). Необязательно использовать this.setState()везде, но когда вам нужно, я предлагаю использовать Redux вместо этого в 99% случаев, возвращаясь к this.setState()1%, исходя из проблем с производительностью.
kumar303
Ведение журнала каждой переменной кажется мне аналогом помещения всего в Redux и, как правило, нецелесообразным. Если исключить некоторые вещи из Redux, это не отменяет возможности всего, что есть в Redux, если состояние разделено. Т.е. я все еще могу отлаживать свою логику вызова API, которая передается через Redux, даже если состояние поля выбора - нет. У OP есть смысл - для использования Redux требуется больше кода в нескольких местах, и, возможно, это не оправдано в конкретном примере, который они перечислили.
JD Sandifer
На самом деле, возможно, вы не сможете отладить логику API. Это моя точка зрения. Очень сложно предвидеть сценарии, в которых вы нарушите путешествие во времени, поэтому лучше просто поместить все состояния (включая состояние поля выбора) в Redux, пока не возникнет проблема с производительностью.
kumar303