我们最近从 Angular 切换到 React + Flux 来构建一个相当复杂的业务应用程序。
采用一个将所有状态作为属性传递到组件树的容器组件的方法并不是为我们开发应用程序的实用方法,因为该应用程序使用类似页面的大模态。足够的状态确实会传递给模态,以便它们将数据加载到它们的存储中。
我遇到的问题是我需要将一些初始状态(作为道具传递)放入模态组件的存储中。在这篇文章中,Facebook的好人说,当同步不是目标时,使用道具作为初始状态是可以的。
这是我目前将初始状态放入商店的方式:
var ABC = React.createClass({
...
getInitialState: function() {
return ABCStore.getInitialABCState(this.props.initialA);
},
...
var ABCStore = Reflux.createStore({
...
init: function() {
_state = {
a: null,
b: 'B init',
c: 'C init'
};
},
getInitialABCState: function(initialA) {
_state.a = initialA;
return _state;
},
getABCState: function() {
return _state;
}
...
我不确定这样做的最佳实践是什么,或者这是否是 Flux 反模式?
你用getInitialState()
来改变商店的状态,我觉得不对。你至少应该在componentWillMount
这样做。
我会在componentWillMount
触发一个操作,并让存储处理程序更新存储的内部状态(这应该始终是不断变化的情况)。然后,组件的存储更改处理程序可以使用当前称为"初始状态"的任何数据
当您提供第三个参数并且Reflux.connect
mixin factory(在引擎盖下使用Reflux.listenTo
)自动为您处理时,Reflux.listenTo
执行此操作。下面是一个示例:
var Actions = Reflux.createActions({"doIt"});
var Store = Reflux.createStore({
listenables: [Actions],
init: function() {
this.state = "I like to";
},
onDoIt: function() {
this.state = "Do it";
this.trigger(this.state);
},
getInitialState: function() {
return this.state;
}
});
var DoItButton = React.createClass({
mixins: [Reflux.connect(Store, "label")],
onClick: function() {
Actions.doIt();
},
render: function() {
return (<div onClick={this.onClick}>{this.state.label}</div>);
}
});
就像其他海报所说,最好的办法是在componentWillMount
中触发一个动作。在 ES6 中,这通常是通过 constructor
.
下面是如何使用 ES6 执行此操作的示例:
(请注意,AuthorActions.initAuthors()
依赖于实现,这只是一个例子。这可能会从数据库获取初始状态。最重要的是,此操作应将具有初始状态的有效负载调度给调度程序)
var _authors = [];
var AuthorStoreInstance;
class AuthorStore extends EventEmitter {
constructor(props) {
super(props);
}
init() {
AuthorActions.initAuthors();
this.emitChange();
}
addChangeListener(cb) {
this.on(CHANGE_EVENT, cb);
}
removeChangeListener(cb) {
this.removeListener(CHANGE_EVENT, cb);
}
emitChange() {
this.emit(CHANGE_EVENT);
}
getAllAuthors() {
return _authors;
}
addAuthor(author) {
_authors.push(author);
this.emitChange();
}
setAuthors(authors) {
_authors = authors;
}
};
AuthorStoreInstance = new AuthorStore();
Dispatcher.register((action) => {
switch(action.actionType) {
case ActionTypes.CREATE_AUTHOR:
AuthorStoreInstance.addAuthor(action.author);
break;
case ActionTypes.INITIALIZE:
AuthorStoreInstance.setAuthors(action.initialData.authors);
break;
default:
//do nothing
}
});
AuthorStoreInstance.init();
export default AuthorStoreInstance;
请注意,init 函数不是构造函数的一部分。这是因为在构造 authorStore 时,AuthorActions.initAuthors
的回调尚未向调度程序注册。
初始化应在向调度程序注册回调后进行。
编辑:为清楚起见,initAuthors
可能看起来像这样:
initAuthors() {
var authors = AuthorAPI.getAllAuthors();
Dispatcher.dispatch({
actionType: ActionTypes.INITIALIZE,
initialData: {
authors: authors
}
});
}