После пары месяцев работы с React + Flux я столкнулся с тем же вопросом и попробовал несколько разных подходов. Я пришел к выводу, что лучший способ это иметь дело с действиями обновления данных, как локальных и удаленных:
# COMPONENT
TodoItems = React.createClass
componentDidMount: ->
TodoStore.addListener("CHANGE", @_onChange)
_onChange: ->
@setState {
todos: TodoStore.get()
_onKeyDown: (event) ->
if event.keyCode == ENTER_KEY_CODE
content = event.target.value.trim()
TodoActions.add(content)
render: ->
React.DOM.textarea {onKeyDown: @_onKeyDown}
# ACTIONS
class TodoActions
@add: (content) ->
Dispatcher.handleAction({type: "OPTIMISTIC_TODO_ADD", todo: {content: content}})
APICall.addTodo({content: content})
# STORE
class TodoStore extends EventEmitter
constructor: ->
@todos = [] # this is a nice way of retrieving from localStore
@dispatchToken = @registerToDispatcher()
get: ->
return @todos
registerToDispatcher: ->
Dispatcher.register (payload) =>
type = payload.type
todo = payload.todo
response = payload.response
switch type
when "OPTIMISTIC_TODO_ADD"
@todos.push(todo)
@emit("CHANGE")
when "TODO_ADD"
# act according to server response
@emit("CHANGE") # or whatever you like
#### APICall
class APICall # what can be called an 'action creator'
@addTodo: (todo) ->
response = http.post(todo) # I guess you get the idea
Dispatcher.handleAction({type: "TODO_ADD", response: response})
Как вы можете видеть, «сок» находится в пределах TodoActions
. Когда добавляется todo, TodoActions.add()
может инициировать оптимистичное обновление пользовательского интерфейса через OPTIMISTIC_TODO_ADD
, который будет вставляться в TodoStore.todos
. Параллельно он знает, что это должно быть сообщено серверу. Внешняя сущность - ApiCall
(которая может считаться создателем действия) - несет ответственность за удаленную часть этого действия, и когда вы получаете ответ, он следует своему нормальному курсу TodoStore
, который может действовать соответствующим образом.
Если вы сделаете магазины ответственными за управление удаленным контентом, вы добавите к нему дополнительный уровень сложности, что сделало меня менее уверенным в состоянии данных в определенный момент.
Позволяет себе это:
class TodoActions
# TodoActions is `dumb`, only passes data and action types to Dispatcher
@add: (content) ->
Dispatcher.handleAction({type: "TODO_ADD", todo: {content: content}})
# APICall.addTodo({content: content})
class TodoStore extends EventEmitter
# ...
registerToDispatcher: ->
# ...
when "TODO_ADD"
@todos.push(todo)
# now the store has to push it to the server
# which means that it will have to call actions or the API directly = BAD
# lest assume:
APICall.addTodo({content: content})
# it also generates some uncertainty about the nature of the event emit:
# this change can guarantee that data was persisted within the server.
@emit("CHANGE")
Решение я представил первый предлагает хороший способ делать оптимистические обновления пользовательского интерфейса, обработки ошибок и отображение загрузки показаний, насколько я испытал.