从概念上讲,我如何编写通量存储以避免将不相关的数据混合在一起
Conceptually, how do I write my flux Stores to not mix up unrelated data together?
假设我有一个依赖Flux的应用程序。
大多数Flux教程告诉您的Components
应该监听Store
上的change
事件,并相应地渲染数据。这种方法非常适合小型和简单的用例,但是我在稍微复杂一点的场景中遇到了一个问题:
我有一份客户名单,我可以按居住城市(华盛顿、纽约等)进行筛选。此列表在url /customers/by-city
下可用,可以用以下代码表示:
var CustomersList = React.createClass({
getInitialState() {
return {
city: 'Washington',
customers: []
};
},
componentWillMount: function() {
CustomersActions.retrieveForCity(this.state.city);
CustomersStore.on('change', this.handleNewData);
},
componentWillUnmount: function() {
CustomersStore.off('change', this.handleNewData);
},
render: function() {
return <FilteredTable filters={['city']}
onCityChange={this.handleCityChange}
data={this.state.customers} />;
},
handleCityChange: function(state) {
CustomersActions.retrieveForCity(this.state.city);
this.setState({city: city});
},
handleNewData: function(customers) {
this.setState({customers: customers});
}
});
每次我想按不同的城市进行筛选时,CustomersActions
都会发出AJAX请求,响应会转到Dispatcher
。然后CustomersStore
拾取它,将其存储为data
,并发出change
事件。几乎是标准的Flux。
现在,据我所知,没有办法将change
事件与它的实际行为联系起来。因此,想象以下场景:
- 我用
San Francisco
过滤表格 - 我改变了主意,在AJAX请求完成之前,我点击了一些导航链接(由react处理,没有页面重新加载),最后我会看到一个不同的url,例如
/customers/shortlisted
。此URL下还有另一个可用组件:ShortlistedCustomers
ShortlistedCustomers
类似于CustomersList
——为了显示数据,它通过CustomerActions
发出ajax请求,并在CustomersStore
上侦听change
事件- 现在,技巧部分-第二个ajax请求在第一个请求之前完成,发出两个
change
事件,用户的表中出现错误的数据
如何"正确"解决此问题?我对最简单的解决方案感兴趣,也许是FB的人自己推荐的?我意识到我可以取消第一个AJAX,或者只按照发出请求的顺序处理响应,但这很快就会失控。
请注意,这个问题并不是针对这个案例的,但它是一个更普遍的问题。例如,如果我想添加更多的方式来触发AJAX请求,或者添加更多依赖于同一Store的组件,那么该解决方案应该适用。
当然,有几种可行的方法可以解决这种情况,每种方法都有自己的优缺点。以下是一些我认为仍然符合Flux的内容。
请记住,我不知道你的应用程序的全部范围,所以其中一些可能对你来说不可行。
客户商店收听已调度的API请求操作
- 发送一个操作以指示已发送API请求
- CustomersStore在调度此操作时清除其状态
也可以用于创建加载状态。
客户存储将其响应存储在存储桶中
- 为/by-city终结点请求的数据将存储在CustomersStore中的"byCity"哈希下
- "/by city的组件现在通过指定此哈希来访问其数据,例如CustomersStore.getData("byCity")"
- 以相同的方式存储和检索/入围的数据
现在您也许可以利用一些缓存逻辑。
创建重置客户的操作存储
- 当CustomersStore收到此"重置"操作时,它将清除其存储的数据
- /在适当的生命周期功能期间,按城市和/入围组件调度"重置"操作
这将帮助你在一个组件内处理同样的问题太
这些想法很少,我相信它们仍然会遵循Flux原理。希望这是有用的!
在更复杂的应用程序中,使用Reflux或Redux可能会做得更好。使用Reflux,您可以使用参数发射,让控制组件根据需要路由数据。
import Reflux from 'reflux';
import Actions from './Actions';
import AddonStore from './Addon.Store';
import MixinStoreObject from './Mixin.Store';
function _GotData(data) { this.data1 = data; BasicStore.trigger('data1'); }
let BasicStoreObject = {
init() { this.listenTo(AddonStore, this.onAddonTrigger); },
data1: {},
listenables: Actions,
mixins: [MixinStoreObject],
onGotData1: _GotData,
onAddonTrigger() { BasicStore.trigger('data2'); },
getData1() { return this.data1; },
getData2() { return AddonStore.data2; },
getData3() { return this.data3; }
}
const BasicStore = Reflux.createStore(BasicStoreObject);
export default BasicStore;
import React from 'react';
import BasicStore from './../flux/Basic.Store';
let AppCtrlSty = {
height: '100%',
padding: '0 10px 0 0'
}
const getState = () => {
return {
Data1: BasicStore.getData1(),
Data2: BasicStore.getData2(),
Data3: BasicStore.getData3()
};
};
class AppCtrlRender extends React.Component {
render() {
let data1 = JSON.stringify(this.state.Data1, null, 2);
let data2 = JSON.stringify(this.state.Data2, null, 2);
let data3 = JSON.stringify(this.state.Data3, null, 2);
return (
<div id='AppCtrlSty' style={AppCtrlSty}>
React 1.4 ReFlux with SuperAgent<br/><br/>
Data1: {data1}<br/><br/>
Data2: {data2}<br/><br/>
Data3: {data3}<br/><br/>
</div>
);
}
}
export default class AppCtrl extends AppCtrlRender {
constructor() {
super();
this.state = getState();
}
componentDidMount() { this.unsubscribe = BasicStore.listen(this.storeDidChange.bind(this)); }
componentWillUnmount() { this.unsubscribe(); }
storeDidChange(id) {
switch (id) {
case 'data1': this.setState({Data1: BasicStore.getData1()}); break;
case 'data2': this.setState({Data2: BasicStore.getData2()}); break;
case 'data3': this.setState({Data3: BasicStore.getData3()}); break;
default: this.setState(getState());
}
}
}
ShortListedCustomers
和CustomersList
应具有/"从单独的存储中提取其数据"[或从公共存储中提取单独的属性]
当操作/存储触发数据已到达的事件时,只有当前渲染的组件才会使用适合它的数据重新渲染。
(话虽如此,我认为你应该转向redux,甚至是逐渐的-不可变性和reducer中的排序将帮助你解决这些问题)
- 三角库可以与firefox一起使用,但不能在Chrome中使用
- 把两个数字加在一起,得到5+10=510,而不是15
- 不同对象之间的递归,并将它们唯一地组合在一起,不重复
- 在不引起递归的情况下将两个淘汰变量连接在一起
- 如何让两个不相关的 React 组件一起工作
- 在使用 jQuery 单击不相关的按钮后,如何防止特定动画运行
- 节点.js将我的模块连接在一起而不会变得一团糟
- 在不相关的事件之后重新绑定 .toggle() 事件
- 由 React 组件抛出的错误,被捕获在不相关的 promise 的 catch 块中
- html5 type=“date” 在 AngularJS 中不与 ngmodel 一起显示
- 如何将两个不相关的元素粘在一起
- 如果将php和javascript混合在一起不起作用,请使用简写
- 为什么选择范围和弹出窗口不能在javascript中一起工作
- 将装饰为html元素的内容附加在一起;不起作用
- 一种通过程序在元素及其元素之间传递不相关属性的方法:before
- Javascript值似乎是交替的,而不是添加在一起的
- 将两个代码集成在一起时,Javascript函数不起作用
- 如何将两个段落连接在一起以内联方式显示,而不会使文本移动
- Raphael悬停函数没有'与其他潜水艇在一起时不起作用
- 从概念上讲,我如何编写通量存储以避免将不相关的数据混合在一起