我正在努力学习Flux,并且已经观看并阅读了这些令人惊叹的资源
我仍然不明白Flux
架构(Action
,Dispatcher
或Store
)的哪一部分负责与API交谈,前提是我的API是异步,并且能够推送数据 - 即当新数据可用时我得到一个事件。
此图片显示Action
正在与API通信,但多个代码示例显示Action
仅触发Dispatcher
..
答案 0 :(得分:2)
如果您将Actions的角色视为通知Stores更新的状态数据,那么在调用Action之前(例如,在组件的事件处理程序中),实际获取新数据的API调用应该是明智的。但是,您可能不希望在整个视图中分散与API相关的逻辑。为避免这种情况,有时会在上图中的View和Action之间引入ActionCreators模块。
通过调用适当的Actions来进行API调用和处理返回数据的方法可以在ActionCreators中收集,因此它们将松散地耦合到您的视图。例如,
user clicks login ->
click handler calls ActionCreator.login(), which makes the API call ->
result is passed to Stores by calling Actions ->
Stores update their state accordingly
如果您的服务器可以通过诸如websockets之类的东西推送更新,则相应的事件侦听器也可以调用ActionCreators中定义的方法,因此您的所有操作都从一个地方发出。或者,您可以将用户启动的ActionCreators和服务器启动的ActionCreators拆分为单独的模块。无论哪种方式,我认为这实现了良好的关注分离。
答案 1 :(得分:2)
在使用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
之内。添加待办事项后,TodoActions.add()
可以通过OPTIMISTIC_TODO_ADD
触发乐观的UI更新,该更新将插入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")
我首先提供的解决方案提供了一种很好的方式,可以对UI进行乐观更新,处理错误并显示加载指示,直到我经历过。