client- and server-side route are different when using react-router server rendering behind proxy

276 views Asked by At

Here is my problem,

  1. I have a front server (apache or nginx) and had some configs like proxy_pass "iamurl/server_render/" to "backend.iamurl.com:3000/".
  2. I have a server rendering react-router programme running on the "backend.iamurl.com:3000" server. (react ,react-router, koa2 and redux).
  3. When I run it on the client side everything is right.
  4. When I run it on the server side, at the first time the request on the server (koa2),i get ctx.url = / so the router matched. But when renderToString() finish and the client had received the response, the location.path is "/server_render", so react-router does't render what i want.

I know the problem is different path on the client- and server-side, but I think this situation(using proxy) is very common in the big company. How can I run correct when the browser received the server rendering response?

I am looking for everyone's idea.

my routes code (share between client and server side)

    <Route path='/' component={Connector}>
        <Route component={BaseLayout}>
            <IndexRoute components={Home} onEnter={onRouteChange.bind(this, 'home')}/>
            <Route path="articleDetail/:id" components={ArticleDetail} onEnter={onRouteChange.bind(this, 'home')}/>
            <Route path="about" components={About} onEnter={onRouteChange.bind(this, 'about')}/>
            <Route path="joinUs" components={JoinUs} onEnter={onRouteChange.bind(this, 'JoinUs')}/>
        </Route>
    </Route>

here is my server rendering code

async function serverRender(ctx, next, renderProps) {
    return new Promise((resolve, reject) => {
        fetchArticlesAPI({API_URL, page: 1}, apiResult => {
            const homeReducer = {
                "home": {
                    fetched: true,
                    data: apiResult.dataList,
                    times: 1,
                    page: 1
                }
            };
            const preloadedState = {"home": homeReducer.home};
            const store = createStore(rootReducer, preloadedState);

            const html = renderToString(
                <Provider store={store}>
                    <RouterContext {...renderProps} />
                </Provider>
            );

            const finalState = store.getState();
            const finalStateToClient = JSON.stringify(finalState).replace(/</g, '\\x3c');


            const body = ctx.render('index', {
                title: "盘古首页(同构)",
                dev: argv.env === 'development',
                finalStateToClient,
                html
            });
            resolve(body);
        });
    });
}

export default async (ctx, next) => {
    const {redirectLocation, renderProps} = await _match({routes: routes, location: ctx.url});

    if (redirectLocation) {
        ctx.redirect(redirectLocation.pathname + redirectLocation.search)
    } else if (renderProps) {
        await serverRender(ctx, next, renderProps)
    } else {
        await next()
    }

}
0

There are 0 answers