仅对初始页面加载使用服务器端呈现

时间:2016-07-08 14:50:06

标签: javascript reactjs react-router

我想使用react的server-side-render来获取用户的初始状态。在此之后,我更愿意使用websockets / ajax /客户端路由来处理应用程序。

这是我到目前为止所拥有的

 function handleRender(req,res){

    getInitialState(id_token)
      .then(function(initialState){
        const store = createStore(rootReducer,initialState)
        console.log('store.getState() ',store.getState())
        const html = renderToString(
          <Provider store={store}>
            <App/>
          </Provider>
        )
        res.send(renderFullPage(html,initialState))
      })
      .catch(function(err){
        console.log('error')
      })
  }

  const renderFullPage = (html,initialState) => {
    return `
      <!doctype html>
      <html>
        <head>
          <title>Redux Universal</title>
        </head>
        <body>
          <div id="app"><div>${html}</div></div>
          <script>
            window.__INITIAL_STATE__= ${JSON.stringify(initialState)}
          </script>
          <script src="/bundle.js"></script>
        </body>
      </html>`
  }

我的客户端index.js非常标准

const initialState = window.__INITIAL_STATE__

export const store = createStore(rootReducer,initialState)


ReactDOM.render(
  <Provider store={store}>
    <Router history={browserHistory}>
      <Route path="/" component={App} />
      <Route path ="/project" component={Project} />
    </Router>
  </Provider>
  ,document.getElementById('app')
)

以上效果很好。当我在客户端导航到/ project时。 Project组件呈现。

然而,当我在/ project处刷新页面时 - 我会在客户端路由器移动到/ project之前快速呈现/页面。

此外,每当我在路线之间切换时,我再次点击服务器,这是我不想要的。

我知道这应该发生,因为刷新再次点击服务器导致它发回

<Provider store={store}>
    <App/>
  </Provider>

呈现app组件,之后react-router再次呈现/ project组件。

有没有办法从服务器获取window.__INITIAL_STATE__和初始HTML,而不必在每次刷新/路由更改时都发送html。

我不想在每次路线改变时都打到服务器,这是我所相信的普遍反应。

对我来说最重要的是在页面加载时获取用户的初始状态。我更喜欢将应用程序作为spa(仅用于初始渲染/状态和api请求的命中服务器)

1 个答案:

答案 0 :(得分:1)

我很确定你错过了将服务器端请求的路由与您的路由器路由器匹配的部分。

import { RoutingContext, match } from 'react-router';
import createLocation from 'history/lib/createLocation';
import routes from './react-routes';

app.get('/*', (req, res, next) => {
  // create a "location" object from the requested url
  const location = createLocation(req.url);

  // match the location to the react routes we have
  match({ routes, location }, (err, redirect, renderProps) => {
    if (err) {
      console.error(err);
      return res.status(500).end('Internal server error');
    }

    if (!renderProps) return res.status(404).end('Not found');

    getInitialState(id_token).then((initialState) => {
      const store = createStore(rootReducer,initialState);
      const html = renderToString(
        <Provider store={store}>
          {() =>
            <RoutingContext {...renderProps} />
          }
        </Provider>
      );
      res.send(renderFullPage(html,initialState));
    });
  });
});

结帐this isomorphic redux example app。并非所有内容都适用于您的情况,但请查看server.jsclient.jsroutes.js