React-Router: 如果存在异步路由,服务器端和客户端都需要用 “match”

工程中遇到的问题,所以记录下来。

假设有下面这样的异步路由:


  ...
  
  

访问 /dashboard 需要看看用户是否登录过,这个过程可能是一个异步的 API 调用,大概样子如下:

const requireAuthentication = (nextState, replace, cb) => {
   loadUserInfo(store).then((user) => {
     if (!user) replace('/login')
     cb()
   })
   .catch(err) { cb(err) }
}

在服务器端渲染的时候,代码片段是这样的:

  match({
    history,
    routes: getRoutes(store),
    location: req.originalUrl
  },
  (error, redirectLocation, renderProps) => {
    if (redirectLocation) {
      res.redirect(redirectLocation.pathname + redirectLocation.search)
    } else if (error) {
      console.error('ROUTER ERROR:', pretty.render(error))
      res.status(500)
      req.send('You'd like to say sorry for this exception.')
    } else if (renderProps) {
      res.send('\n' +
        ReactDOM.renderToString(
          YourRootComponent,
          store={store}   // render the Redux initial data into the server markup
        />))
    }
  })

macth 确保之前路由定义的一系列异步操作都已经完成。但是,大家如果看 react-router 的文档,则往往不知道其实也需要在 Client 端进行同样的操作:

match({ history, routes }, (error, redirectLocation, renderProps) => {
  const { location } = renderProps
  ReactDOM.render(
    
      
        {YourRoutes}
      
    ,
    YourContainerElement
  )
})

如果不使用 match,那么你在直接访问 /login 页面的时候,会收到下面警告:

Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
 (client) 
                    

你可能感兴趣的:(React-Router: 如果存在异步路由,服务器端和客户端都需要用 “match”)