在React / Flux中管理商店数据依赖性

时间:2014-07-13 14:36:01

标签: javascript reactjs-flux

我有一个使用Facebook的Flux架构开发的网络应用程序。该页面有两个视图:一个显示TODO项目列表。第二个视图显示一组随机的TODO项目。

显然,商店需要管理两个问题。第一个是可用的TODO列表。第二个是随机选择的TODO项目列表。

因此我有一个TODOStore,他们只关心管理可用的TODO项目。它包含loadTODOsaddTODOdeleteTODOeditTODO的操作。在启动时,此商店不会加载所有TODO项目。我希望它仅在必要时从数据库中检索TODO项目列表。

第二家商店是RandomTODOListStore。它的职责是管理随机选择的TODO项目。在我看来,RandomTODOListStore应使用TODOStore通过TODOStore.getTODOItems()访问TODO项目。

function RandomTODOListStore() {
   var $randomTODOs = [];

   dispatcher.register(function(payload) {
        var action = payload.action;

        switch (action.actionType) {
            case Constants.LOAD_RANDOM_TODO:
                loadRandomTODO();
                break;
        }
    });

    function loadRandomTODO() {
        $randomTODOs = selectRandom(TODOStore.getTODOList());
        emit("change");
    }
}

问题在于,如前所述,TODOStore在启动时不会加载TODO项目。

问题是:" RandomTODOListStore如何保证TODOStore已经检索过TODO项?"

3 个答案:

答案 0 :(得分:4)

建议的Flux实现使用waitFor方法来同步商店。我创建Reflux以便通过让商店能够收听其他商店来更轻松地处理这个问题。该功能的作用是它将保证链中的前一个商店已经处理了它的数据。

界面有点不同,因为Reflux不依赖于字符串常量来识别动作,所以这里是一个例子。

var TodoActions = Reflux.createActions(['load']);

var todoStore = Reflux.createStore({
    init: function() {
        // Listen to the load action
        this.listenTo(TodoActions.load, this.loadActions);
    },
    loadActions: functions() {
        var loadedActions = [];
        // load your actions into loadedActions
        // and do then the following inside the ajax 
        // callback when it is done:
        this.trigger(loadedActions);
    }
});

var randomTodoStore = Reflux.createStore({
    init: function() {
        // You may listen to stores as well
        this.listenTo(todoStore, onLoadedActions);
    },
    onLoadedActions: function(loadedActions) {
        // loaded actions will be passed in from the
        // dotoStores change event trigger

        // you may do your select random from loaded 
        // actions list   
    }
});

// Invoke the action
TodoActions.load();

希望这是有道理的。

答案 1 :(得分:2)

我认为这就是为什么Flux架构提到需要使用waitFor提到的case Constants.LOAD_RANDOM_TODO: Dispatcher.waitFor([TodoStore.dispatcherIndex],this.loadRandomTODO); break; 方法同步商店

如果要同步商店,您的RandomTODOListStore可能应该如下所示:

Constants.LOAD_RANDOM_TODO

然后在您的TodoStore上,您可以对TodoStore.getRandom()作出反应并加载待办事项列表(如果尚未加载)。

但是我认为这是过于复杂的,你可能不应该为随机待办事项创建另一个商店,因为这个商店将(我猜)总是委托给真正的todo商店。只需使用Constants.LOAD_TODOS代替

修改

是TodoStore不需要知道它是如何使用的。因此,当您想要获得随机待办事项时,您可以使用您使用的相同事件,例如TodoStore.getTodos()[randomIndex],然后通过RandomTODOListStore

从该商店获取随机待办事项

如果两个组件同时触发事件,则可以忽略第二个事件

另一个解决方案是让case Constants.TODOS_LOADED: this.randomTodos = randomSubset(TodoStore.getTodos,subsetSize); break; 对加载的事件做出反应并选择主存储的一些待办事项以将它们放入RandomTODOListStore中:

{{1}}

你可以从here启发自己:对于异步数据,不仅有一个事件被触发而是2(命令+成功/失败)

答案 2 :(得分:0)

您的RandomTODOListStore需要等待TODOStore。您可以使用此库(我的)https://github.com/kjda/ReactFlux

轻松实现此目的
var ReactFlux = require('react-flux');

var TODOConstants = ReactFlux.createConstants(['LOAD'], 'TODO');

var TODOActions = ReactFlux.createActions({
    load: [TODOConstants.TODO_LOAD, function(){
      //load your todos here
      return { todos: [{title: 'do this'}, {title: 'do that'}]}
    }]
});

var TODOStore = ReactFlux.createStore({
    getTodos: function(){
       return this.getState().todos;
    }
}, [
   [TODOConstants.TODO_LOAD_SUCCESS, function(payload){
      this.setState({
          todos: payload.todos
      });
   }]
]);

var RandomTODOListStore = ReactFlux.createStore({
    selectRandomFromList: function(todos){
      //..... select some here
    }
}, [

   /**
    * This waits for TODOStore to process the message first
    */
   [TODOConstants.TODO_LOAD_SUCCESS, [TODOStore], function(payload){
        this.selectRandomFromList(payload.todos);
   }]

]);

现在,当您的应用启动时,您只需要调用操作

  

TODOActions.load();