Isomorphic React / Redux App:避免在服务器渲染上额外获取API

时间:2017-01-08 16:56:18

标签: javascript reactjs redux react-router isomorphic-javascript

我有一个同构(也就是通用)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/falseisRehydratedStateFresh = true/false这样的全球状态。但我真的想避开全球各州。

有解决方案吗?或者一个不需要全局状态的解决方案?

0 个答案:

没有答案