套接字在哪里适合Flux单向数据流?

evk*_*ine 5 javascript flux websocket socket.io reactjs

套接字在哪里适合Flux单向数据流?我已经阅读了两种思路,即远程数据应该进入Flux单向数据流.我看到获取Flux应用程序的远程数据的方式是在进行服务器端调用时,例如,在承诺中解析或拒绝.在此过程中可能会触发三种可能的操作:

  1. 乐观更新视图的初始操作 (FooActions.BAR)
  2. 解决异步承诺时的成功操作 (FooActions.BAR_SUCCESS)
  3. 异步承诺被拒绝时的错误操作 (FooActions.BAR_ERROR)

商店将监听操作并更新必要的数据.我已经看到了来自动作创建者和商店内部的服务器端调用.我使用动作创建器进行上述过程,但我不确定是否应该通过Web套接字获取数据.我想知道插座适合下图.

在此输入图像描述

And*_*ahl 11

使用Flux与WebSockets或普通的旧HTTP请求/轮询的方式确实没有区别.您的商店负责在应用程序状态更改时发出更改事件,如果该更改来自UI交互,WebSocket或发出HTTP请求,则不应从商店外部看到它.这实际上是Flux的主要优点之一,无论应用程序状态在何处发生变化,它都会经历相同的代码路径.

一些Flux实现倾向于使用动作/动作创建器来获取数据,但我不同意这一点.

操作是发生修改应用程序状态的事情.这就是"用户更改了一些文本并点击保存"或"用户删除了一个项目".想想像数据库的事务日志这样的操作.如果丢失了数据库,但保存并序列化了所有发生的操作,则可以重放所有这些操作,最终得到丢失的相同状态/数据库.

所以像"给我带有身份X的项目"和"给我所有项目"这样的事情不是行动,而是问题,关于该申请状态的问题.在我看来,这些商店应该通过您在这些商店中公开的方法来回应这些问题.

使用动作/动作创建器进行提取很诱人,因为提取需要异步.通过将异步内容包装在操作中,您的组件和存储可以完全同步.但是,如果你这样做,你会模糊一个动作的定义,它也会强迫你假设你可以将整个应用程序状态放在内存中(因为你只能在内存中得到答案时才能同步响应).

所以这就是我如何看待Flux和不同的概念.

商店

这显然是您的应用程序状态所在的位置.商店封装和管理状态,是该状态实际发生突变的唯一地方.它也是当状态发生变化时发出事件的地方.

商店还负责与后端通信.当状态发生变化并且需要与服务器同步时,商店与后端通信,并且当它需要内存中没有的数据时,它还与服务器通信.它有类似的方法get(id),search(parameters)等等.这些方法对于您的问题,他们都返回的承诺,即使国家可以放入内存.这很重要,因为您最终可能会遇到状态不再适合内存的情况,或者无法在内存中进行过滤或进行高级搜索的情况.通过从您的问题方法返回承诺,您可以在从内存返回或询问后端之间切换,而无需更改商店外的任何内容.

操作

我的行为非常轻量级,并且他们对持久化它们所包含的突变一无所知.他们只是意图从组件变异到商店.对于较大的应用程序,它们可以包含一些逻辑,但绝不会包含服务器通信.

组件

这些是您的React组件.它们通过调用商店中的问题方法并呈现这些方法的返回值来与商店交互.他们还订阅change了商店曝光的活动.我喜欢使用更高阶的组件,这些组件只是包装另一个组件并将props传递给它.一个例子是:

var TodoItemsComponent = React.createClass({
  getInitialState: function () {
    return {
      todoItems: null
    }
  },
  componentDidMount: function () {
    var self = this;
    TodoStore.getAll().then(function (todoItems) {
      self.setState({todoItems: todoItems});
    });

    TodoStore.onChange(function (todoItems) {
      self.setState({todoItems: todoItems});
    });
  },
  render: function () {
    if (this.state.todoItems) {
      return <TodoListComponent todoItems={this.state.todoItems} />;
    } else {
      return <Spinner />;
    }
  }
});

var TodoListComponent = React.createClass({
  createNewTodo: function () {
    TodoActions.createNew({
      text: 'A new todo!'
    });
  },
  render: function () {
    return (
      <ul>
        {this.props.todoItems.map(function (todo) {
          return <li>{todo.text}</li>;
        })}
      </ul>
      <button onClick={this.createNewTodo}>Create new todo</button>
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

在这个例子中,TodoItemsComponent它是更高阶的组件,它包含了与商店进行通信的细节.它呈现了TodoListComponent它何时获取待办事项,并在此之前渲染一个微调器.由于它将todo项目作为道具传递给TodoListComponent该组件,因此只需要专注于渲染,并且只要商店中发生任何变化,它就会重新渲染.并且渲染组件保持完全同步.另一个好处是,TodoItemsComponent它只专注于获取数据并传递数据,使其对任何需要todos的渲染组件都非常可重用.

更高阶的组件

术语高阶分量来自术语高阶函数.高阶函数是返回其他函数的函数.因此,更高阶的组件是一个只包装另一个组件并返回其输出的组件.

  • 并非所有人都同意Stores应该与Web服务器进行通信.事实上,许多人没有.http://stackoverflow.com/q/25630611/95190 (2认同)