ReactJS Flux Utils 组件

ReactJS Flux Utils components

有兴趣article 它描述了 Flux Utils.

中公开的 4 个主要 类
  1. 商店
  2. ReduceStore
  3. MapStore(从 3.0.0 中删除)
  4. 容器

但是在某些情况下应该使用什么还不是很清楚。 ReduceStoreContainer 只有 2 个示例,但不幸的是没有其他示例。

您能否解释一下这 4 个组件的基本用法:whenwhere他们应该在现实生活中使用?

扩展答案和代码示例将不胜感激!

更新:

MapStore 从 3.0.0

开始 removed

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

对于这些,以几乎相反的顺序进行实际上很有用。

容器

这不是 FluxStore 的子class,因为不出所料,它不是一家商店。 Container 是 React UI 组件的包装器 class,可自动从指定存储中提取状态。

例如,如果我有一个 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(UserListContainer);

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

我相信这是对 Facebook React 编码原则的相当直接的扩展,其中 UI 的每一位都存在于高层 "Container." 因此得名。

何时使用

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

ReduceStore

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

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

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

,我的程序中的任何内容都不会改变

无论如何,ReduceStore 应该只实现其文档中明确列出的方法。 getInitialState() 应该确定初始状态,reduce(state, action) 应该转换 state 给定 action (并且根本不使用 this:那将是 non-deterministic/have 方effects),并且 getState() & 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;
    }
}

请注意,none 的转换明确取决于对象的当前状态:它们仅对传递给它们的 state 变量进行操作。这意味着 store 的一个实例可以为同一 store 的另一个实例计算状态。在 FB Flux 的当前实现中不是那么有用,但仍然。

何时使用

  • 如果您喜欢纯函数式编程(耶!)
  • 如果您不喜欢它而无法使用明确基于该假设构建的框架 (redux, NuclearJS)
  • 并且您可以明智地编写一个纯功能商店(大多数商店都可以,如果不能,多考虑一下架构可能有意义)

注意:此class 不能确保 您的代码是纯函数的。我的猜测是,如果您不自己检查,它就会坏掉。

我会一直使用这家商店。除非我可以使用...

FluxMapStore[已弃用]

这个 class 不再是 Flux 的一部分!

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

他们有方便的方法从状态中获取键和值:

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

何时使用

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

FluxStore

这将我们带到 FluxStore:包罗万象的 Store class 和 Flux Store 概念的通用实现。

另外两家店是它的后代。

在我看来,该文档对其用法相当清楚,所以我就此打住

何时使用

  • 如果您不能使用其他两个 Store 实用程序 classes 来保存您的数据
  • 并且您不想推出自己的商店

就我而言,那永远不会:我更喜欢像 redux 和 NuclearJS 这样的不可变框架,因为它们对我来说更容易推理。我注意以纯粹功能性的方式构建我的商店。但如果你不这样做,这个 class 很好。