【提问】为什么使用react-route,每次都会刷新页面

#1

使用react-router,在后台server端

app.use((req, res) => {
  match({ routes, location: req.url }, (err, redirectLocation, renderProps) => {
    if (err) {
      res.status(500).end(`Internal Server Error ${err}`);
    } else if (redirectLocation) {
      res.redirect(redirectLocation.pathname + redirectLocation.search);
    } else if (renderProps) {
      const initialState = {
        auth: {
          isAuthenticated: false,
          currentUser: {}
        }, open: false }
      const store = configureStore(initialState)
      const state = store.getState()
      const params = Object.assign(req.query, renderProps.params)

      fetchComponentDataBeforeRender(store.dispatch, renderProps.components, params)
      .then(() => {
        // 这里redux的store给Provider,再通过mapStateToProps给对应的容器组件
        const html = renderToString(
          <Provider store={store}>
            <RouterContext {...renderProps} />
          </Provider>
        )
        res.send(renderFullPage(html, store.getState()));
      })
    } else {
      res.status(404).send('Not found');
    }
  })
})

const renderFullPage = (appHtml, initialState) => {
  return `
  <!doctype html public="storage">
  <html lang="en">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script>
      window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};
    </script>
    <div id="app">
      ${appHtml}
    </div>
  </body>

  <script type="text/javascript" src="http://localhost:8080/javascripts/bundle.js" charset="utf-8"></script>
  <script type="text/javascript" src="http://${serverHost}/javascripts/common.js" charset="utf-8"></script>
  <script type="text/javascript" src="http://${serverHost}/javascripts/bundle.js" charset="utf-8"></script>
  </html>
  `
}

下面是fetchComponentDataBeforeRender文件的代码:

export function fetchComponentDataBeforeRender(dispatch, components, params) {
  const needs = components.reduce((prev, current) => {
    return (current.need || [])
      .concat((current.WrappedComponent ? current.WrappedComponent.need : []) || [])
      .concat(prev);
  }, []);
  const promises = needs.map(need => dispatch(need(params)));
  return Promise.all(promises);
}

routes.js文件:

import React from 'react'
import { Route, IndexRoute } from 'react-router'
import AppLayout from './AppLayout'
import LoginForm from './LoginForm'
import RegisterForm from './RegisterForm'
import MoviesGridList from './MoviesGridList'
import MovieCardShow from './MovieCardShow'

module.exports = (
  <Route path="/" component={AppLayout}>
    <IndexRoute component={MoviesGridList} />
    <Route path="/movies" component={MoviesGridList} />
    <Route path="/movies/:id" component={MovieCardShow} />
    <Route path="/users/login" component={LoginForm} />
    <Route path="/users/register" component={RegisterForm}/>
  </Route>
)

每次点击链接都会刷新页面,重新加载bundle.js和common.js,为什么不是根据路由加载对应的component呢?

#2

你想要的是 按需加载吗?

google webpack 按需加载

#3

你看看这个,http://lilumovie.herokuapp.com/ 至少appbar不要每次都重新加载

#4

不会吧。我没用过服务端渲染,只是在服务端设置每一个请求都返回同一html文件,在浏览器切换页面除了发出一些xhr请求不会有其他任何请求了。更不需要重新加载js文件。

#5

我的虽然是send字符串,应该跟sendFile差不多,这是代码:https://github.com/TsaiKoga/lilu_movie/blob/master/server.js

#6

按需加载不是这个意思,你的后台返回的是一个html模板,这个模板script标签是固定的加载bundle.js和common.js,而你的每个component都打包在bundle里面,当然是一起返回给前端了。

除非在打包阶段,把每个component单独打包出来,用script异步加载,这样才能实现你需要的功能。

再说说为什么你用了react-router还是需要每次都刷新整个页面,因为你用在了服务端,react-router应该在前端配置,这样只需要第一次打开网页需要一次性请求bundle之外,其他时候都不需要重复刷新页面。

或许你想用的服务端渲染,但是服务端渲染不是那么容易解决的,还是乖乖的前端处理吧。

#7

我之前通过这个https://github.com/reactjs/react-router-tutorial/tree/master/lessons/13-server-rendering
学习react-router,然后它也是server端返回html,为什么它好像不同页面不会再次请求bundle.js

#8

有什么心得吗

#9

我改成react-router的Link标签,后它就不经过server端,直接局部渲染;这刚好是我想要的;
但是有个问题就是当有params时,会出错,原因是我把api请求数据放在server端的fetchComponentDataBeforeRender,前台redux mapstateToprops只是将后台一开始得到的state数据内容给props;所以将其改为当前端路由更新component用mapStateToProps去过滤数据。