Ответ 1
Пролистав код и прочитав документацию по методу, вот что я могу решить (я сам не использовал эти классы, так как использую другие фреймворки Flux).
На самом деле полезно пойти в почти обратном порядке для них.
Контейнер
Это не подкласс FluxStore
потому что, что неудивительно, это не магазин. Container
- это класс-оболочка для ваших компонентов пользовательского интерфейса React, который автоматически извлекает состояние из указанных хранилищ.
Например, если у меня есть приложение чата, управляемое React, с компонентом, в котором перечислены все мои друзья, вошедшие в систему, я, вероятно, хочу, чтобы оно LoggedInUsersStore
состояние извлечения из LoggedInUsersStore
, который гипотетически представлял бы собой массив этих пользователей.
Мой компонент будет выглядеть примерно так (полученный из примера кода, который они предоставляют):
import {Component} from 'react';
import {Container} from 'flux/utils';
import {LoggedInUsersStore} from /* somewhere */;
import {UserListUI} from /* somewhere */;
class UserListContainer extends Component {
static getStores() {
return [UsersStore];
}
static calculateState(prevState) {
return {
loggedInUsers: LoggedInUsersStore.getState(),
};
}
render() {
return <UserListUI counter={this.state.counter} />;
}
}
const container = Container.create(UserListContainer);
Эта оболочка автоматически обновляет состояние компонента, если его зарегистрированные хранилища изменяют состояние, и делает это эффективно, игнорируя любые другие изменения (т.е. предполагает, что компонент не зависит от других частей состояния приложения).
Я полагаю, что это довольно прямое продолжение принципов кодирования Facebook React, в которых каждый бит пользовательского интерфейса находится в высокоуровневом "контейнере". Отсюда и название.
Когда использовать
- Если данный компонент React полностью зависит от состояния нескольких явных хранилищ.
- Если это не зависит от реквизита сверху. Контейнеры не могут принимать реквизиты.
ReduceStore
ReduceStore
- это хранилище, полностью основанное на чистых функциях ---functions, которые являются детерминированными на своих входах (поэтому одна и та же функция всегда возвращает одно и то же для одного и того же ввода) и не дает видимых побочных эффектов (поэтому они не влияют на другие части код).
Например, лямбда (a) => { return a * a; }
(a) => { return a * a; }
чисто: оно детерминировано и не имеет побочных эффектов. (a) => { echo a; return a; }
(a) => { echo a; return a; }
нечист: у него есть побочный эффект (печать a
). (a) => { return Math.random(); }
(a) => { return Math.random(); }
нечисто: оно недетерминировано.
Целью ReduceStore
является упрощение: сделав свой магазин чистым, вы можете сделать определенные предположения. Поскольку сокращения являются детерминированными, каждый может выполнить сокращения в любой момент и получить тот же результат, поэтому отправка потока действий практически идентична отправке необработанных данных. Аналогично, отправка необработанных данных совершенно разумна, поскольку вам не было гарантировано никаких побочных эффектов: если вся моя программа сделана из ReduceStore
s, и я перезаписываю состояние одного клиента на состояние другого (вызывая необходимые перерисовки), я гарантирую отличная функциональность. Ничто в моей программе не может измениться из-за действий, а не данных.
В любом случае, ReduceStore
должен реализовывать только методы, явно указанные в его документации. getInitialState()
должен определять начальное состояние, getInitialState()
reduce(state, action)
должен преобразовывать state
заданного action
(а не использовать this
вообще: это было бы недетерминированным/иметь побочные эффекты), и getState()
& areEqual(one,two)
должен обрабатывать отделение необработанного состояния от возвращенного состояния (чтобы пользователь не мог случайно изменить его).
Например, счетчиком будет разумный ReduceStore
:
class TodoStore extends ReduceStore {
getInitialState() {
return 0;
}
reduce(state, action) {
switch(action.type) {
case 'increment':
return state + 1;
case 'decrement':
return state - 1;
case 'reset':
return 0;
default:
return state;
}
getState() {
// return 'this._state', which is that one number, in a way that doesn't let the user modify it through something like 'store.getState() = 5'
// my offhand JS knowledge doens't let me answer that with certainty, but maybe:
var a = this._state + 1;
return a - 1;
}
}
Обратите внимание, что ни одно из преобразований явно не зависит от текущего состояния объекта: они работают только с той переменной state
они были переданы. Это означает, что экземпляр хранилища может вычислять состояние для другого экземпляра того же хранилища. Не очень полезно в текущей реализации FB Flux, но все же.
Когда использовать
- Если вам нравится чисто функциональное программирование (ууу!)
- и если вам не нравится это достаточно, чтобы использовать рамки явно построенные с этим предположением (перевождите, NuclearJS)
- и вы можете разумно написать магазин, который является чисто функциональным (большинство магазинов могут, и если они не могут, возможно, имеет смысл подумать об архитектуре немного больше)
Примечание: этот класс не гарантирует, что ваш код является чисто функциональным. Я думаю, что это сломается, если вы сами не проверите это.
Я бы всегда использовал этот магазин. Если только я не смогу использовать...
FluxMapStore [ УСТАРЕЛО ]
Этот класс больше не является частью Flux!
Это подкласс ReduceStore
. Это для таких чисто функциональных магазинов, которые оказываются внутри Карт. В частности, карты Immutable.JS (еще одна вещь FB!).
У них есть удобные методы для получения ключей и значений из состояния:
WarrantiesStore.at('extended')
а не WarrantiesStore.getState().get('extended')
.
Когда использовать
- Как указано выше, но также
- если я могу представить этот магазин с помощью карты.
FluxStore
Это приводит нас к FluxStore: универсальному классу Store и общей реализации концепции Flux Store.
Два других магазина являются его потомками.
Мне кажется, что документация достаточно ясна в отношении его использования, поэтому я оставлю это на этом
Когда использовать
- Если вы не можете использовать два других класса
Store
util для хранения ваших данных - и вы не хотите катить свой собственный магазин
В моем случае это никогда не будет: я предпочитаю неизменные фреймворки, такие как redux и NuclearJS, потому что мне легче рассуждать. Я забочусь о том, чтобы структурировать свои магазины исключительно функционально. Но если нет, этот класс хорош.