Flux 是将异步数据获取到我的 React.JS 视图的正确解决方案吗
Is Flux the right solution to get async data to my React.JS views
我目前正在使用 React.JS 设计 Web 应用程序的架构。在 React 中,数据流是单向的。有时(经常)我们想在视图之间进行交流。 React 使用 flux 解决了这个问题。到目前为止一切顺利,我现在拥有存储(共享)数据的商店。
现在我想知道 flux 是否也是这个老问题的正确解决方案:
一个视图,比如说 table 需要来自它应该呈现的服务器的数据。我对 React 没有那么多经验,因此请原谅我,如果这是一个愚蠢的问题,但是 flux 也是从服务器获取数据并将其解析为注册视图的正确解决方案吗?如果是这样,是否有处理异步数据的最佳实践?如果不是,从服务器获取数据以进行反应视图的合适方法是什么?
我实际上不希望视图调用数据。在我看来,视图应该尽可能愚蠢...
一种常见的方法是在视图代码的 componentDidMount() 方法中初始化异步调用,并正确渲染它。
代码可能因不同的通量实现而不同,但您明白了
getInitialState() {
return {
rows: MyStore.getState().rows
}
}
componentDidMount() {
this.listenTo(MyStore, this.onChange)
MyActions.fetchData()
}
onChange() {
this.setState(this.getInitialState())
}
....
render() {
if (!this.state.rows) {
return <span />
}
return <Table rows={this.state.rows}>
}
至于容器组件,用不用完全由你决定。
..is flux also the right solution for getting data from a server and
parse it to the registered views?
你可以用助焊剂做到这一点。通量大约 Action Creators. In the flux architecture the idea is that you have a Controller View that registers itself with a Store。控制器视图是您的智能组件,它从商店获取它的状态,通常它呈现child组件,哑组件,它将(部分)状态作为属性传递给它的 child(ren).
例如,当您从服务器获取数据时,需要触发 Action Creator,此 Action Creator 随后将调用 Web API 实用程序来执行实际请求。成功后,Web API 实用程序将调用一个 Server Action Creator,它会调度一个包含从服务器接收到的有效载荷的动作。然后任何已注册的 Store 将处理此操作并发出更改事件。这样,当 Store 的数据发生变化时,任何对 Store 感兴趣的 Controller View 都会收到通知。控制器视图将更新其状态并重新呈现自身和任何 child(ren) 以显示正确的数据。
这意味着您可以在控制器视图的 componentDidMount
方法中调用 Action Creator 以从服务器获取数据(请注意,尽管此挂钩仅执行一次!)。
最初,Controller View 将向 store 请求数据并获取,例如,一个空数组,该数组将被设置为 Controller View 的状态,而 Controller View 将呈现一些空的东西。然后在获取数据后,Controller View(由 Store 通知)将再次从 Store 中检索数据,只是现在它不会为空。控制器视图相应地更新它的状态,触发重新渲染并显示适当的数据。
这一点的本质在这个最小的(伪)代码中得到了体现:
// Action Creator: actions/data.js
import { fetchData } from '../utils/server';
export function fetch() {
fetchData();
}
// Server Action Creator: actions/data-server.js
import dispatcher from '../dispatcher';
export function receiveData(data) {
dispatcher.dispatch({
type: 'RECEIVE_DATA',
payload: data
});
}
// Web API Utility: utils/server.js
import request from 'request';
import { receiveData } from '../actions/data-server';
export function fetchData() {
request.get('https://api.com/v1/data', receiveData);
}
// Store: stores/store.js
import dispatcher from '../dipatcher';
import { EventEmitter } from 'events';
const CHANGE_EVENT = 'change';
let __data__ = [];
const Store = Object.assign({}, EventEmitter.prototype, {
emitChange () {
this.emit(CHANGE_EVENT);
},
addChangeListener (callback) {
this.on(CHANGE_EVENT, callback);
},
removeChangeListener (callback) {
this.removeListener(CHANGE_EVENT, callback);
},
getData () {
return __data__;
}
});
Store.dispatchToken = dispatcher.register(function (action) {
switch (action.type) {
case 'RECEIVE_DATA':
__data__ = action.payload;
Store.emitChange();
break;
}
});
export default Store;
// Controller View: components/List.jsx
import React from 'react';
import Store from '../stores/Store');
import { fetch } from '../actions/data';
var __getState = function () {
return {
data: Store.getData()
};
};
export default React.createClass({
getInitialState () {
return __getState();
},
componentWillMount () {
fetch();
},
componentDidMount () {
Store.addChangeListener(this._onChange);
},
componentWillUnMount () {
Store.removeChangeListener(this._onChange);
},
_onChange () {
this.setState( __getState() );
},
render () {
const { data } = this.state;
return (
<div className="list">
<ul>
{ data.map(dataItem => <li>{ dataItem.name }</li> )}
</ul>
</div>
);
}
});
查看更详细的通量示例 here。
I actually don't want a view to call for the data. In my opinion a
view should be as stupid as possible...
最好区分 smart 和 dumb 组件。这个想法是智能组件保持状态和调用操作,而哑组件不依赖于应用程序的其余部分。这创建了一个清晰的关注点分离,并允许更好的组件的可重用性和可测试性。阅读更多相关信息 here。
除了助焊剂之外,还有一些有趣的替代品。例如有 redux。它使用单个不可变状态 Object(即存储),其中只允许 reducer(纯函数)通过操作修改应用程序状态。
如果您主要从服务器检测和渲染 read-only 数据,一定要查看 react-refetch。
我目前正在使用 React.JS 设计 Web 应用程序的架构。在 React 中,数据流是单向的。有时(经常)我们想在视图之间进行交流。 React 使用 flux 解决了这个问题。到目前为止一切顺利,我现在拥有存储(共享)数据的商店。
现在我想知道 flux 是否也是这个老问题的正确解决方案: 一个视图,比如说 table 需要来自它应该呈现的服务器的数据。我对 React 没有那么多经验,因此请原谅我,如果这是一个愚蠢的问题,但是 flux 也是从服务器获取数据并将其解析为注册视图的正确解决方案吗?如果是这样,是否有处理异步数据的最佳实践?如果不是,从服务器获取数据以进行反应视图的合适方法是什么?
我实际上不希望视图调用数据。在我看来,视图应该尽可能愚蠢...
一种常见的方法是在视图代码的 componentDidMount() 方法中初始化异步调用,并正确渲染它。
代码可能因不同的通量实现而不同,但您明白了
getInitialState() {
return {
rows: MyStore.getState().rows
}
}
componentDidMount() {
this.listenTo(MyStore, this.onChange)
MyActions.fetchData()
}
onChange() {
this.setState(this.getInitialState())
}
....
render() {
if (!this.state.rows) {
return <span />
}
return <Table rows={this.state.rows}>
}
至于容器组件,用不用完全由你决定。
..is flux also the right solution for getting data from a server and parse it to the registered views?
你可以用助焊剂做到这一点。通量大约 Action Creators. In the flux architecture the idea is that you have a Controller View that registers itself with a Store。控制器视图是您的智能组件,它从商店获取它的状态,通常它呈现child组件,哑组件,它将(部分)状态作为属性传递给它的 child(ren).
例如,当您从服务器获取数据时,需要触发 Action Creator,此 Action Creator 随后将调用 Web API 实用程序来执行实际请求。成功后,Web API 实用程序将调用一个 Server Action Creator,它会调度一个包含从服务器接收到的有效载荷的动作。然后任何已注册的 Store 将处理此操作并发出更改事件。这样,当 Store 的数据发生变化时,任何对 Store 感兴趣的 Controller View 都会收到通知。控制器视图将更新其状态并重新呈现自身和任何 child(ren) 以显示正确的数据。
这意味着您可以在控制器视图的 componentDidMount
方法中调用 Action Creator 以从服务器获取数据(请注意,尽管此挂钩仅执行一次!)。
最初,Controller View 将向 store 请求数据并获取,例如,一个空数组,该数组将被设置为 Controller View 的状态,而 Controller View 将呈现一些空的东西。然后在获取数据后,Controller View(由 Store 通知)将再次从 Store 中检索数据,只是现在它不会为空。控制器视图相应地更新它的状态,触发重新渲染并显示适当的数据。
这一点的本质在这个最小的(伪)代码中得到了体现:
// Action Creator: actions/data.js
import { fetchData } from '../utils/server';
export function fetch() {
fetchData();
}
// Server Action Creator: actions/data-server.js
import dispatcher from '../dispatcher';
export function receiveData(data) {
dispatcher.dispatch({
type: 'RECEIVE_DATA',
payload: data
});
}
// Web API Utility: utils/server.js
import request from 'request';
import { receiveData } from '../actions/data-server';
export function fetchData() {
request.get('https://api.com/v1/data', receiveData);
}
// Store: stores/store.js
import dispatcher from '../dipatcher';
import { EventEmitter } from 'events';
const CHANGE_EVENT = 'change';
let __data__ = [];
const Store = Object.assign({}, EventEmitter.prototype, {
emitChange () {
this.emit(CHANGE_EVENT);
},
addChangeListener (callback) {
this.on(CHANGE_EVENT, callback);
},
removeChangeListener (callback) {
this.removeListener(CHANGE_EVENT, callback);
},
getData () {
return __data__;
}
});
Store.dispatchToken = dispatcher.register(function (action) {
switch (action.type) {
case 'RECEIVE_DATA':
__data__ = action.payload;
Store.emitChange();
break;
}
});
export default Store;
// Controller View: components/List.jsx
import React from 'react';
import Store from '../stores/Store');
import { fetch } from '../actions/data';
var __getState = function () {
return {
data: Store.getData()
};
};
export default React.createClass({
getInitialState () {
return __getState();
},
componentWillMount () {
fetch();
},
componentDidMount () {
Store.addChangeListener(this._onChange);
},
componentWillUnMount () {
Store.removeChangeListener(this._onChange);
},
_onChange () {
this.setState( __getState() );
},
render () {
const { data } = this.state;
return (
<div className="list">
<ul>
{ data.map(dataItem => <li>{ dataItem.name }</li> )}
</ul>
</div>
);
}
});
查看更详细的通量示例 here。
I actually don't want a view to call for the data. In my opinion a view should be as stupid as possible...
最好区分 smart 和 dumb 组件。这个想法是智能组件保持状态和调用操作,而哑组件不依赖于应用程序的其余部分。这创建了一个清晰的关注点分离,并允许更好的组件的可重用性和可测试性。阅读更多相关信息 here。
除了助焊剂之外,还有一些有趣的替代品。例如有 redux。它使用单个不可变状态 Object(即存储),其中只允许 reducer(纯函数)通过操作修改应用程序状态。
如果您主要从服务器检测和渲染 read-only 数据,一定要查看 react-refetch。