【问题标题】:Managing store data dependency in React/Flux在 React/Flux 中管理存储数据依赖
【发布时间】:2014-09-03 14:48:16
【问题描述】:

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

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

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

第二家商店是RandomTODOListStore。它的职责是管理随机选择的 TODO 项。在我看来,RandomTODOListStore 应该使用TODOStore.getTODOItems() 通过TODOStore 访问 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项目?”

【问题讨论】:

    标签: javascript reactjs-flux


    【解决方案1】:

    提议的 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();
    

    希望这是有道理的。

    【讨论】:

      【解决方案2】:

      我认为这就是为什么 Flux 架构提到需要使用 waitFor 方法同步存储的原因提到 here

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

      case Constants.LOAD_RANDOM_TODO:
        Dispatcher.waitFor([TodoStore.dispatcherIndex],this.loadRandomTODO);
        break; 
      

      然后在您的 TodoStore 上,您可以对 Constants.LOAD_RANDOM_TODO 做出反应并加载尚未加载的待办事项列表。

      但是我认为这过于复杂,您可能不应该为随机 todos 创建另一个存储,因为这个存储(我猜)总是委托给真正的 todo 存储。只需改用TodoStore.getRandom()

      编辑

      是的 TodoStore 不需要知道它是如何使用的。因此,当您想获得一个随机的待办事项时,您可能可以使用您使用的相同事件,例如Constants.LOAD_TODOS,然后使用TodoStore.getTodos()[randomIndex]从该商店获得一个随机待办事项

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

      另一种解决方案是让RandomTODOListStore 对加载的事件做出反应并选择主商店的一些待办事项将它们放入RandomTODOListStore:

      case Constants.TODOS_LOADED:
        this.randomTodos = randomSubset(TodoStore.getTodos,subsetSize);
        break; 
      

      您可以从Async exemple from Fluxxor 中激发自己的灵感:对于异步数据,不仅会触发一个事件,还会触发 2 个事件(命令 + 成功/失败)

      【讨论】:

      • 是的,我确实考虑过。问题在于 TODOStore 不应该关心其他人如何使用它。它不应该对 RandomTODOListStore 动作做出反应。想象一下,每当我有其他需要 TODO 项的东西时,TODOStore 会很快变得臃肿。
      【解决方案3】:

      您的 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();

      【讨论】:

        猜你喜欢
        • 2014-11-17
        • 2015-12-12
        • 2015-05-03
        • 2015-04-24
        • 1970-01-01
        • 2013-10-11
        • 2017-12-16
        • 1970-01-01
        • 2015-12-08
        相关资源
        最近更新 更多