javascript - 仅将服务器端渲染用于初始页面加载

标签 javascript reactjs react-router

我想使用react的服务器端渲染来仅获取用户的初始状态。之后,我更喜欢使用 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 之前,我会快速渲染/页面。

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

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

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

渲染应用程序组件,然后react-router再次渲染/project组件。

有没有一种方法可以让我从服务器获取window.__INITIAL_STATE__和初始HTML,而不必在每次刷新/路由更改时发送html。

我不想在每次路由更改时都访问服务器,这就是我所相信的通用 react 。

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

最佳答案

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

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.js , client.js ,和routes.js .

关于javascript - 仅将服务器端渲染用于初始页面加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38269595/

相关文章:

javascript - ExpressJS 支持 ejs 和 React 前端的混合

reactjs - MIME 类型 ('text/html' ) 不可执行,并且启用了严格的 MIME 类型检查

javascript - 即使更改时目标输入也为 :focus,

javascript - Vim 中的 Syntastic 声明函数可能无法返回

javascript - 单击按钮即可编辑标签 View - Sproutcore

javascript - react 。登录后新路由器

reactjs - React-i18next 未在使用 create-react-app 创建的 React 应用程序中加载 json 翻译文件

node.js - React Router v6 中的 protected 路由,使用 useState,但始终返回 false

javascript - 如何在 react-router v4 中设置事件链接的样式?

javascript - 如何从 Web Worker 访问 chrome.history?