我有一个同构(也就是通用)React应用程序,我正在努力学习。
后端是服务器和客户端发出请求的单独项目。因此,呈现React应用程序的服务器不同。
服务器渲染设置如下,稍微简化一下:
const
data = {
body: '',
initialState: {}
},
store = configureStore(); // Middleware and so on
match({location, routes}, (err, redirectLocation, renderProps) => {
// Handle error
// Handle redirect
fetchData(store.dispatch, renderProps.components, renderProps.params)
.then(() => {
data.body = renderToString({
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>
});
data.initialState = store.getState(); // dehydrate
return renderToStaticMarkup(<HtmlComponent {...data} />);
})
.then((html) => res.status(200).send('<!doctype html>' + html))
.catch((err) => res.status(500).send(err.stack));
});
方法fetchData()
如下所示:
export function fetchData(dispatch, components, params) {
const needs = components.reduce((prev, current) => {
if(!current) return [];
return Object.keys(current).reduce((acc, key) => {
return current[key].hasOwnProperty('needs') ? current[key].needs.concat(acc) : acc;
}, prev);
}, []),
promises = needs.map((need) => dispatch(need(params)));
return Promise.all(promises);
}
连接的React组件设置如下:
const Component = React.createClass({
statics: {
needs: [
Actions.getHistory
]
},
componentWillMount: function() {
const needs = this.constructor.needs;
for(let i = 0, len = needs.length; i < len; i++) {
this.props.dispatch(needs[i]());
}
},
// Code
};
在服务器上,在执行react应用程序之前,使用needs
完成路由的fetchData()
操作。在客户端中,我希望在needs
上调度componentWillMount()
操作,但前提是它不是初始路由。在初始路由上,操作已在服务器上完成,商店在客户端中重新水合。
问题在于我不知道如何避免在服务器上的componentWillMount()
和客户端中的初始路由上调度操作。这意味着当页面被服务器渲染时,动作将被分派三次。
我已经设置了项目来学习如何编写同构应用程序。这种设置是我认为很常见的,我已经看到在互联网上使用了很多。但我还没有找到一种方法来防止双重/三重动作的发送。
我唯一能想到的就是像isServerRender = true/false
和isRehydratedStateFresh = true/false
这样的全球状态。但我真的想避开全球各州。
有解决方案吗?或者一个不需要全局状态的解决方案?