Предположим, у меня есть приложение, использующее Flux.
В большинстве руководств по Flux говорится, что ваш Components
должен прослушивать событие change
на Store
и соответствующим образом отображать данные. Этот подход отлично подходит для небольших и простых случаев использования, однако у меня есть проблема в чуть более сложном сценарии:
У меня есть список клиентов, которых я могу отфильтровать по городу проживания (Вашингтон, Нью-Йорк и т. д.). Этот список доступен по URL-адресу /customers/by-city
и может быть представлен следующим кодом:
var CustomersList = React.createClass({
getInitialState() {
return {
city: 'Washington',
customers: []
};
},
componentWillMount: function() {
CustomersActions.retrieveForCity(this.state.city);
CustomersStore.on('change', this.handleNewData);
},
componentWillUnmount: function() {
CustomersStore.off('change', this.handleNewData);
},
render: function() {
return <FilteredTable filters={['city']}
onCityChange={this.handleCityChange}
data={this.state.customers} />;
},
handleCityChange: function(state) {
CustomersActions.retrieveForCity(this.state.city);
this.setState({city: city});
},
handleNewData: function(customers) {
this.setState({customers: customers});
}
});
Каждый раз, когда я хочу отфильтровать по другому городу, запрос AJAX выдается CustomersActions
, ответ идет на Dispatcher
. Затем CustomersStore
берет его, сохраняет как data
и выдает событие change
. Почти стандартный материал Flux.
Теперь, насколько я понимаю, нет никакого способа связать это событие change
с тем, что оно на самом деле сделало. Итак, представьте себе следующий сценарий:
- Я фильтрую таблицу по
San Francisco
- Я передумал, и до того, как запрос AJAX будет завершен, я нажимаю на какую-то навигационную ссылку (обрабатывается реакцией, без перезагрузки страницы), и я оказываюсь на другом URL-адресе, например.
/customers/shortlisted
. По этому URL-адресу доступен еще один компонент:ShortlistedCustomers
. ShortlistedCustomers
похож наCustomersList
- для отображения данных он отправляет запрос ajax черезCustomerActions
и прослушивает событиеchange
наCustomersStore
- Теперь хитрость - второй запрос ajax выполняется раньше первого, выдаются два события
change
, и пользователь получает неправильные данные в своей таблице.
Как решить это "правильно"? Меня интересует самое простое возможное решение, может быть, что-то, что порекомендовали сами ребята из FB? Я понимаю, что мог бы, например. отменить первый AJAX или обрабатывать ответы только в том порядке, в котором были отправлены эти запросы, но это быстро выйдет из-под контроля.
Обратите внимание, что этот вопрос относится не только к этому случаю, но и к более общему вопросу. Например. решение должно применяться, если я хочу добавить больше способов запуска запроса AJAX или больше компонентов, зависящих от одного и того же хранилища.
setState()
— это diff, а не новое состояние; поэтому он сливается с существующим состоянием - person Adam Zielinski   schedule 05.11.2015setState() Performs a shallow merge of nextState into current state
- person Adam Zielinski   schedule 05.11.2015