React/Reflux 数据流:一个组件在 DOM 中两次
React/Reflux data flow: One component twice in DOM
假设我有以下树:
<LandingPage>
<PageHeader>
<Menu>
<ShoppingCart>
</Menu>
</PageHeader>
<MainPage>
<ShoppingCart>
</MainPage>
</LandingPage>
我们关心的组件是 ShoppingCart。
安装它 (componentDidMount) ShoppingCart 会触发一个操作,因此 ShoppingCartStore 会向服务器发出请求并returns 文章列表 - 触发 ShoppingCart 的重新渲染。
现在的设置方式,总是会有两次请求和两次重新渲染,因为这两个组件都在 dom.
一种解决方案是让一个共同的根触发这些请求,但那将是 LandingPage - 并且必须通过 PageHeader 和 Menu 以及 MainPage 传递数据。
有更好的解决办法吗?够好了吗?
我对所有数据请求使用 api.store。我在条目 app.js 中调用 api.store。然后我使用 api.store 侦听初始数据请求的操作。
app.js
'use strict';
import React from 'react';
import ReactDom from 'react-dom';
import AppCtrl from './components/app.ctrl.js';
import Actions from './actions/api.Actions';
import ApiStore from './stores/Api.Store';
window.ReactDom = ReactDom;
Actions.apiInit();
ReactDom.render( <AppCtrl />, document.getElementById('react') );
api.store
import Reflux from 'reflux';
import Actions from '../actions/api.Actions';
import ApiFct from '../utils/sa.api';
let ApiStoreObject = {
newData: {
"React version": "0.14",
"Project": "ReFluxSuperAgent",
"currentDateTime": new Date().toLocaleString()
},
listenables: Actions,
apiInit() { ApiFct.setData(this.newData); },
apiInitDone() { ApiFct.getData(); },
apiSetData(data) { ApiFct.setData(data); }
}
const ApiStore = Reflux.createStore(ApiStoreObject);
export default ApiStore;
在连接到商店的组件中,初始状态调用商店数据,因此如果数据已经存在,您就可以获取它。
import React from 'react';
import BasicStore from '../stores/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 0.14 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); };
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());
}
};
}
来自https://github.com/calitek/ReactPatterns React.14/ReFluxSuperAgent.
假设我有以下树:
<LandingPage>
<PageHeader>
<Menu>
<ShoppingCart>
</Menu>
</PageHeader>
<MainPage>
<ShoppingCart>
</MainPage>
</LandingPage>
我们关心的组件是 ShoppingCart。
安装它 (componentDidMount) ShoppingCart 会触发一个操作,因此 ShoppingCartStore 会向服务器发出请求并returns 文章列表 - 触发 ShoppingCart 的重新渲染。
现在的设置方式,总是会有两次请求和两次重新渲染,因为这两个组件都在 dom.
一种解决方案是让一个共同的根触发这些请求,但那将是 LandingPage - 并且必须通过 PageHeader 和 Menu 以及 MainPage 传递数据。
有更好的解决办法吗?够好了吗?
我对所有数据请求使用 api.store。我在条目 app.js 中调用 api.store。然后我使用 api.store 侦听初始数据请求的操作。 app.js
'use strict';
import React from 'react';
import ReactDom from 'react-dom';
import AppCtrl from './components/app.ctrl.js';
import Actions from './actions/api.Actions';
import ApiStore from './stores/Api.Store';
window.ReactDom = ReactDom;
Actions.apiInit();
ReactDom.render( <AppCtrl />, document.getElementById('react') );
import Reflux from 'reflux';
import Actions from '../actions/api.Actions';
import ApiFct from '../utils/sa.api';
let ApiStoreObject = {
newData: {
"React version": "0.14",
"Project": "ReFluxSuperAgent",
"currentDateTime": new Date().toLocaleString()
},
listenables: Actions,
apiInit() { ApiFct.setData(this.newData); },
apiInitDone() { ApiFct.getData(); },
apiSetData(data) { ApiFct.setData(data); }
}
const ApiStore = Reflux.createStore(ApiStoreObject);
export default ApiStore;
在连接到商店的组件中,初始状态调用商店数据,因此如果数据已经存在,您就可以获取它。
import React from 'react';
import BasicStore from '../stores/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 0.14 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); };
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());
}
};
}
来自https://github.com/calitek/ReactPatterns React.14/ReFluxSuperAgent.