3

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

Данные, которые я имею в виду, например:

  • константа IN_BROWSER, которая находится в браузере true строит и false в узле.
  • постоянной IS_MOBILE, который инициализируется при старте в браузере
  • данные пользователя, которые в настоящее время вошли в системе,
  • URL в API, что я подключиться к (который является локальным, устроив сервер, или производство, в зависимости от конфигурации)

Сейчас у меня есть файл с именем sessionData.js, который хранит эти данные, и всякий раз, когда мне нужно, я require('./sessionData') в моем коде и использовать его. Я могу издеваться над своими модульными тестами, используя rewire, и, поскольку они выполняются последовательно, на данный момент он отлично работает. Это проблематично для styleguide, потому что каждый пример может отображать представление с точки зрения другого пользователя (поэтому в идеале каждый пример будет иметь свой собственный sessionData).

IN_BROWSER В настоящее время global, что также оказывается плохой идеей, поскольку оно неявно зависит от кода инициализации от каждого модуля.

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

Есть ли какой-либо дизайн, чтобы решить его лучше?

ответ

1

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

Например, мой WebPack конфигурации имеет:

new webpack.DefinePlugin({ 
    'process.env': {'NODE_ENV': JSON.stringify(options.env)} 
}), 

Так что я могу использовать process.env.NODE_ENV в переднем конце, как и в заднем конце.

Я открытым исходным кодом мой WebPack конфигурации здесь: https://github.com/agendor/react-webpack-sample/blob/master/webpack.config.js

А вот link for the plugin documentation

Для модульных тестов, я использую test-helper.js класс, определить некоторые глобальные переменные и я требую его в начале каждого теста , Я не уверен, что это хорошая практика, но она отлично работает для нашего проекта. Мы запускаем наши тесты без webpack. Возможно, лучшей практикой было бы иметь определенную конфигурацию webpack для тестов, которые обрабатывают некоторые из этих глобальных переменных.

+0

Это один хороший, но это помогает только для 1-го случая, в 'IN_BROWSER' постоянной. – mik01aj

+0

@ m01 Я думал, вы можете добавить еще один аргумент в плагин, который указывает на ваш 'sessionData.js' модуль, чтобы вы могли использовать его, не требуя каждый раз. Но вам придется возвращать функцию вместо построенного объекта. Не уверен, подходит ли он. – Tulio

+0

Проблема с sessionData заключается в том, что я не хочу, чтобы она была глобальной. Я хочу изменить его динамически для каждого модульного теста или каждого примера стилей. – mik01aj

0

Похоже, что react context - путь.

К сожалению, API в настоящее время нестабилен, например. React.withContext устарел в 0,13-альфа, а документы говорят, что API изменится в будущем, но кажется, что контекст как таковой isn't going to be deprecated.

1

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

structure = { 
    dataItem1: stuff, 
    dataItem2: stuff2, 
    dataItemCallback: { var foo = stuff here; } 
} 

Вы можете назвать это как:

this.props.structure.dataItem1; 
this.props.structure.dataItem2; 

Чтобы обновить то, что вы всегда можете позвонить:

this.props.structure.dataItemCallback(newData); 

Кроме того, если вы пропустите его через реквизит, теперь все компоненты могут засавить если что-либо в изменении структуры.

+0

Кажется хорошей идеей, но потом я волнуюсь, что структура будет становиться все больше и больше (и тем более сложнее насмехаться или поддерживать). Не могли бы вы рассказать о том, как вы можете сохранить его простым и удобным? – mik01aj

+0

Я должен сказать, что потенциально ваши компоненты представления могут быть слишком сложными, если представление должно беспокоиться о структуре, которая много. На уровне представления компоненты должны просто получать реквизиты и визуализировать их без какой-либо логики. Контроллеры представлений могут иметь некоторую дополнительную логику, чтобы обрабатывать все те части структуры данных и просто передавать их индивидуально через реквизиты для компонентов немого представления. Как сделать структуру простой и обслуживаемой? Все зависит от ваших индивидуальных потребностей, я полагаю :) – Bruce

0

В некоторых случаях можно реорганизовать компоненты для передачи необходимых данных напрямую, а не в глобальном состоянии. Это не решает проблему, но может значительно уменьшить ее. Вот nice explanation from Dan Abramov:

enter image description here

 Смежные вопросы

  • Нет связанных вопросов^_^