我正在研究React Flux项目,其中异步交互是一项持续的事情,而且在反应生命周期方面我仍然有点不稳定。
在我的有状态组件中,我有一个getStateFromStores函数,如果store中没有状态,则返回false bool,否则返回状态。
正如我现在所说的那样,循环如下:
我的组件中有一个名为getState()的绑定函数(ES6反应类),它只调用getStateFromStores并检查返回值是否为false,如果不是,则调用带状态的setState()。
由于状态变化的通知可能来自不同的来源,我喜欢在一个地方声明逻辑(getState)
状态变化可能来自以下方面:
ComponentDidMount(我应该把它移到initialState吗?) 这是组件生命周期中发生的第一件事。 (除非我们的商店中已经存在状态,否则我们会得到错误的回报)
ComponentWillReceiveProps 如果在父组件中更改了状态,我们会通知组件它应该使用新的道具获取新状态。
存储更改侦听器 当store具有新状态时,getState被调用作为回调(虽然有点问题,因为发出的原因可能是由于给定组件的调用而导致的 - 所以我可能实现onStoreChange作为回调,而后者又调用getState)
我正在玩一个叫做抓取的状态道具,我可以用来控制流量,但这有问题吗? - 因为每次我改变状态它都会触发渲染(?) - 我可以使用静态吗?
我想象以下内容; DidMount触发getState(),getState设置为true,现在所有其他的调用尝试都会因bool检查而失败。
然后我实现了一个resetState,它将状态恢复为默认状态(获取false),然后再次触发getState。
我将所有这些功能抽象为“高阶组件”
谢谢!
答案 0 :(得分:2)
我采取了不同的方法。我发现编写React组件的一大优势是,您可以将组件视为一个独立的单元 - 具有自己的HTML,JavaScript,数据获取 - 甚至样式。它依靠Flux存储来跟踪数据,而不是将数据作为道具传递。
假设您有用户登录并收到一些信息。现在,让我们说用户想要管理他们的帐户。我们可以这样做......
<Account user_info={this.state.user_info} />
这样可以正常工作,但如果帐户知道user_id,那么帐户是否可以获得所需的user_info?这会引导我们......
<Account user_id={this.state.user_info.user_id}>
但是,真的,商店不知道登录用户是谁吗?毕竟,它是获取/存储数据的必要条件。那么为什么不呢......
<Account />
...让Account从商店获取所需数据 - 不需要user_id,因为商店已经知道登录用户。
无论如何,只是一种不同的思考方式。
答案 1 :(得分:1)
我发现在大多数情况下我的工作非常好,就是拥有一个根“控制器组件”。我们现在称它为Controller
。它基本上就像React组件一样 - 但它的责任有点不同。
我认为这只是委托。唯一的责任是从商店获取数据(状态)并将其(作为道具)传递给其子组件,让他们完成所有工作。
这是通过将商店中的数据设置为Controller
的状态来完成的。商店中的任何更改都会(仅)更新其状态Controller
。由于状态作为道具传递给子项,因此商店中的更改将触发使用该数据重新呈现的所有子组件(如果必须)。
我尝试仅将相关数据传递给子组件,但不要太担心它们获取大量数据(或者关于一些额外的重新渲染)。
在实践中,Controller
看起来像这样:
function getStateFromStores() {
return {
players: PlayerStore.getData(),
cards: CardStore.getData()
};
}
var Controller = React.createClass({
getInitialState: function() {
return getStateFromStores();
},
componentDidMount: function() {
PlayerStore.addChangeListener(this._onChange);
CardStore.addChangeListener(this._onChange);
},
componentWillUnmount: function() {
PlayerStore.removeChangeListener(this._onChange);
CardStore.removeChangeListener(this._onChange);
},
_onChange: function() {
this.setState(getStateFromStores());
},
render: function() {
return (
<Component1
players={this.state.players}
cards={this.state.cards}
/>
<Component2
players={this.state.players}
/>
<Component3
cards={this.state.players}
/>
);
}
});
module.exports = Controller;