说我有TodoStore。 TodoStore负责保存我的TODO物品。 Todo项目存储在数据库中。
我想知道将所有待办事项加载到商店的建议方式是什么,以及视图应如何与商店交互以在启动时加载TODO项目。
第一种方法是创建一个loadTodos
动作,它将从数据库中检索Todos并发出TODOS_LOADED
事件。然后,视图将调用loadTodos
操作,然后收听TODOS_LOADED
事件,然后通过调用TodoStore.getTodos()
进行更新。
另一种选择是没有loadTodos
操作,并且TodoStore.getTodos()
将返回与现有TODO项目的承诺。如果TodoStore已经加载了TODO项目,它只返回它们;如果没有,那么它将从数据库中查询并返回检索到的项目。在这种情况下,即使商店现在已经加载了TODO项目,它也不会发出TODOS_LOADED事件,因为getTodos
不是一个动作。
function getTodos() {
if (loaded)
return Promise.resolve($todoItems);
else
return fetchTodoItemsFromDatabase().then(todoItems) {
loaded = true;
$todoItems = todoItems;
return $todoItems;
});
}
我确信很多人会说这会打破Flux架构,因为getTodos
函数正在改变存储状态,只有通过调度程序发送的操作才能更改存储状态。
但是,如果您认为TodoStore的状态是数据库中现有的TODO项目,那么getTodos
并不是真正改变任何状态。 TODO项目完全相同,因此不需要更新或通知视图。唯一的事情是,现在商店已经检索了数据,因此它现在缓存在商店中。从View的角度来看,它不应该真正关心Store的实现方式。如果商店仍然需要从数据库中检索数据,它应该不在乎。所有关注的观点都是他们可以使用Store来获取TODO项目,并且Store会在创建,删除或更改新TODO项目时通知他们。
因此,在这种情况下,视图应该只调用TodoStore.getTodos()来加载自己,并在TODO_CHANGE上注册一个事件处理程序,以便在需要由于添加,删除或更改而自行更新时得到通知。
您如何看待这两种解决方案?他们是否有其他解决方案?
答案 0 :(得分:3)
视图不必是调用loadTodos()的实体。这可能发生在引导程序文件中。
您确定应该尽量将数据流限制为调度有效负载内的操作。有时您需要根据其他商店的状态派生数据,这就是Dispatcher.waitFor()的用途。
与fetchTodoItemsFromDatabase()解决方案类似的Flux是没有其他实体在商店中设置数据。商店正在更新。这很好。
我对此解决方案的唯一严重批评是,如果您实际从服务器获取初始数据,则可能导致渲染延迟。理想情况下,您将使用HTML发送一些数据。您还需要确保要求商店'控制器视图中的数据' getInitialState()方法。
答案 1 :(得分:0)
以下是我对此的看法,非常接近你的。
Store
和Immutable.Record
从Immutable.js Immutable.OrderedMap
维护我的申请状态
以下内容:
function getInitialState() {
return {
todos: TodoStore.getAll()
}
}
TodoStore.getAll
地图为空,APIUtils.getTodos()
方法将通过_todos
请求从服务器检索数据。我主张在Store
中触发的读取数据和ActionCreators
中触发的写入数据。APIUtils
会触发TODO_LIST_RECEIVE_SUCCESS
或TODO_LIVE_RECEIVE_FAIL
等操作,具体取决于回复状态TodoStore
将通过更新其内部状态(使用从操作有效负载创建的Immutable.OrderedMap
填充其内部Immutable.Record
来响应这些操作。如果您想通过基本实现查看示例,请查看this answer about React/Flux and xhr/routing/caching 。
答案 2 :(得分:0)
我知道自问这个问题已有几年了,但它完美地总结了我本周要努力解决的问题。所以为了帮助任何可能遇到这个问题的人,我发现这篇博文真的帮助了Nick Klepinger:"ngrx and Tour of Heroes"。
它专门使用Angular 2和@ ngrx / store,但很好地回答了你的问题。