ReactJS Flux Utils组件

时间:2016-01-28 20:28:33

标签: reactjs flux reactjs-flux

有趣article 它描述了Flux Utils中公开的4个主要类。

  1. 存储
  2. ReduceStore
  3. MapStore(已从3.0.0移除)
  4. 容器
  5. 但是,对于某些情况应该使用什么并不是很清楚。 ReduceStoreContainer只有2个示例,但遗憾的是没有其他示例。

    请您解释这4个组件的基本用法: 何时 应该在现实生活?

    非常感谢扩展答案和代码示例!

    更新

    3.0.0

    开始,MapStore已removed

1 个答案:

答案 0 :(得分:22)

通过浏览code并阅读方法文档,这里有我可以解决的问题(我自己没有使用这些类,因为我使用其他Flux框架)。

对于这些来说几乎是相反的顺序实际上是有用的。

容器

这不是FluxStore的子类,因为毫不奇怪,它不是商店。 Container是React UI组件的包装类,它自动从指定的商店中提取状态。

例如,如果我有一个React驱动的聊天应用程序,其中一个组件列出了我所有已登录的朋友,我可能希望从LoggedInUsersStore获取状态,这假设是一个数组这些用户。

我的组件看起来像这样(从他们提供的代码示例中派生出来):

import {Component} from 'react';
import {Container} from 'flux/utils';

import {LoggedInUsersStore} from /* somewhere */;
import {UserListUI} from /* somewhere */;

class UserListContainer extends Component {
  static getStores() {
    return [UsersStore];
  }

  static calculateState(prevState) {
    return {
      loggedInUsers: LoggedInUsersStore.getState(),
    };
  }

  render() {
    return <UserListUI counter={this.state.counter} />;
  }
}

const container = Container.create(CounterContainer);

如果组件的注册存储更改状态,则此包装器会自动更新组件的状态,并且通过忽略任何其他更改(即,它假定组件不依赖于应用程序状态的其他部分)来有效地执行此操作。

我相信这是Facebook的React编码原则的一个相当直接的扩展,其中每一个UI都存在于一个高级别的容器中。&#34;因此这个名字。

何时使用

  • 如果给定的React组件完全依赖于少数显式存储的状态。
  • 如果依赖于上面的道具。容器不能接受道具。

ReduceStore

ReduceStore是一个完全基于纯函数的商店 - 对其输入具有确定性的函数(因此相同的函数总是返回相同的相同输入的东西)并产生没有可观察到的副作用(因此它们不会影响代码的其他部分)。

例如,lambda (a) => { return a * a; } :它是确定性的,没有副作用。 (a) => { echo a; return a; } 不纯:它有副作用(打印a)。 (a) => { return Math.random(); } 不纯:这是不确定的。

ReduceStore的目标是简化:通过使您的商店是纯粹的,您可以做出某些假设。由于减少是确定性的,任何人都可以随时执行减少并获得相同的结果,因此发送动作流与发送原始数据完全相同。同样,发送原始数据是完全合理的,因为你保证没有副作用:如果我的整个程序是由ReduceStore s组成的,我用另一个状态覆盖一个客户端的状态(调用所需的重绘) ,我保证完美的功能。由于操作而不是数据,我的程序中的任何内容都无法更改。

无论如何,ReduceStore应该只实现其文档中明确列出的方法。 getInitialState()应该确定初始状态,reduce(state, action)应该转换state给定action(并且根本不使用this:这将是不确定的/有边效果)和getState()&amp; areEqual(one,two)应该处理原始状态与返回状态的分离(这样用户就不会意外地修改它)。

例如,计数器将是明智的ReduceStore

class TodoStore extends ReduceStore {
    getInitialState() {
        return 0;
    }

    reduce(state, action) {
        switch(action.type) {
            case 'increment':
                return state + 1;
            case 'decrement':
                return state - 1;
            case 'reset':
                return 0;
            default:
                return state;
    }

    getState() {
        // return `this._state`, which is that one number, in a way that doesn't let the user modify it through something like `store.getState() = 5`
        // my offhand JS knowledge doens't let me answer that with certainty, but maybe:
        var a = this._state + 1;
        return a - 1;
    }
}

请注意,没有任何转换显式依赖于对象的当前状态:它们仅对传递的state变量进行操作。这意味着商店实例可以为同一商店的另一个实例计算状态。在当前的FB Flux实现中并没有那么有用,但仍然如此。

何时使用

  • 如果你喜欢纯函数式编程(耶!)
  • 如果您不喜欢使用根据该假设明确构建的框架(reduxNuclearJS
  • 你可以明智地写一个纯粹功能的商店(大多数商店都可以,如果他们能够更多地考虑一下建筑,那么)

注意:此类不确保您的代码纯粹功能。我的猜测是,如果你不自己检查,它会破裂。

总是使用此商店。除非我能使用......

FluxMapStore [DEPRECATED]

此课程不再是Flux的一部分!

这是ReduceStore的子类。这种纯功能商店恰好是内部地图。具体来说,Immutable.JS映射(另一个FB的东西!)。

他们有方便的方法来从州获取密钥和值:

WarrantiesStore.at('extended')而不是WarrantiesStore.getState().get('extended')

何时使用

  • 如上所述,还
  • 如果我可以使用地图代表这家商店。

FluxStore

这将我们带到FluxStore:全能商店类和Flux商店概念的通用实现。

另外两家店是它的后代。

在我看来,文档中的用法相当清楚,所以我会把它留在那里

何时使用

  • 如果您不能使用其他两个Store util类来保存数据
  • 并且您不想推销自己的商店

在我的情况下,那将永远不会:我更喜欢不可变的框架,如redux和NuclearJS,因为它更容易让我推理。我注意以纯粹的功能方式构建我的商店。但如果你不这样做,这门课很好。