早安全部!
我有一个依赖于商店的反应组件(一个视图),而该商店依赖于从往返服务器中拉出一些状态。
我想要了解的是,如果有一个常见的模式可以解决初始化商店的状态。
现在我想我会做类似的事情:
var SomeView = React.createClass({
componentWillMount: function() {
SomeStore.addChangeListener(this._onChange);
// Go and tell this thing we want to initiliaze our
// state ahead of time. My worry here is obviously
// that when state is updated this fires again so I'd
// need to have some knowledge that the store has been
// initialized which seems very (very) kludgey
SomeActions.init();
},
render: function() {
// Here i'd want to see if I had items available for
// rendering. If I didn't I'd drop on a loading dialog
// or if I did I could render the detail.
},
_onChange: function() {
// this.setState...
}
});
var SomeActions = {
init: function() {
AppDispatcher.dispatch({
actionType: SomeConstants.INIT
});
}
};
var SomeStore = assign({}, EventEmitter.prototype, {
init: function() {
$.get('/round/trip', function(data) {
this.emitChange();
}).bind(this);
}
emitChange: function() {
this.emit(CHANGE_EVENT);
},
addChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback);
}
});
AppDispatcher.register(function(action) {
switch(action.actionType) {
case SomeConstants.INIT:
SomeStore.init()
break;
default:
}
});
我绝对肯定必须有更好的方法。
答案 0 :(得分:1)
我的担心显然是当状态更新时再次激发
componentWillMount
一旦组件注入DOM就触发,状态更新不会触发此方法。但是,如果从DOM中删除组件(例如:不根据某些条件在父组件中呈现它)并稍后再渲染它,则将再次触发该方法。因此,init
将在商店中多次调用。
我相信您应该将http请求代码移动到Web API模块并从componentWillMount
方法向API激活操作,然后API将触发存储并在组件上触发change
事件,将更新状态并重新渲染。这就是Flux的工作原理。
如果您只需要获取一次数据并且您知道您的组件将多次从DOM中删除/添加到DOM中,您应该将api调用到树中的上部组件(表示入口点的组件)小部件或其他东西)。
我建议检查Component Container或更高阶组件模式,它基本上将瘦包装器组件定义为视图组件上的数据层。因此,您可以将视图与数据层完全分开,并且效果很好。
您可能还想检查另一种方法,来自ClojureScript& Om,具有单一的不可变状态。这简化了一切,实际上是我通过React构建应用程序的最佳方式。我为它创建了a starter kit
,对自述文件中的主要概念有一个很好的解释。