如何使用react-router v4预加载数据?

时间:2017-07-03 04:26:38

标签: reactjs react-router-v4

这是来自官方文档(https://reacttraining.com/react-router/web/guides/server-rendering/data-loading)的示例:

 import { matchPath } from 'react-router-dom'

 // inside a request
 const promises = []
 // use `some` to imitate `<Switch>` behavior of selecting only
 // the first to match
 routes.some(route => {
   // use `matchPath` here
   const match = matchPath(req.url, route)
   if (match)
     promises.push(route.loadData(match))
   return match
 })

 Promise.all(promises).then(data => {
   // do something w/ the data so the client
   // can access it then render the app
 })

这份文件让我非常紧张。这段代码不起作用。而这种方法并不奏效!如何在服务器中预加载数据?

1 个答案:

答案 0 :(得分:1)

这就是我所做的 - 这是我从文档中提出来的。

<强> routes.cfg.js

首先以可用于客户端应用程序并导出到服务器上使用的方式设置路由配置。

export const getRoutesConfig = () => [
  {
    name: 'homepage',
    exact: true,
    path: '/',
    component: Dasboard
  },
  {
    name: 'game',
    path: '/game/',
    component: Game
  }
];

...

// loop through config to create <Routes>

服务器

设置服务器路由以使用上面的配置并检查具有名为needs的属性的组件(调用您喜欢的,可能是ssrData或其他)。

// function to setup getting data based on routes + url being hit
async function getRouteData(routesArray, url, dispatch) {
  const needs = [];
  routesArray
    .filter((route) => route.component.needs)
    .forEach((route) => {
      const match = matchPath(url, { path: route.path, exact: true, strict: false });
      if (match) {
        route.component.needs.forEach((need) => {
          const result = need(match.params);
          needs.push(dispatch(result));
        });
      }
    });
  return Promise.all(needs);
}

....

// call above function from within server using req / ctx object
const store = configureStore();  
const routesArray = getRoutesConfig();
await getRouteData(routesArray, ctx.request.url, store.dispatch);
const initialState = store.getState();

<强> container.js / component.jsx

设置组件的数据获取。确保将needs数组添加为属性。

import { connect } from 'react-redux';

import Dashboard from '../../components/Dashboard/Dashboard';
import { fetchCreditReport } from '../../actions';

function mapStateToProps(state) {
  return { ...state.creditReport };
}

const WrappedComponent = connect(
  mapStateToProps,
  { fetchCreditReport }
)(Dashboard);

WrappedComponent.needs = [fetchCreditReport];

export default WrappedComponent;

请注意,此方法适用于连接到匹配路由的组件,而不是嵌套组件。但对我来说这一直很好。路由级别的组件执行数据提取,然后稍后需要它的组件将它传递给它们,或者添加连接器以直接从商店获取数据。