使用 React/Redux 的服务器端呈现,获取 url 参数以传递到 loadData

Server Side Rendering with React/Redux, getting url params to pass into loadData

我很确定为什么这不起作用,但我不确定如何解决它。

我有一个组件,它在末尾使用 loadData() 函数,以便将数据传递到商店成为 SSR。

示例组件类似于

class Test extends Component {
  render(){
    return (
      <div>Test</div>
    )
  }
}

const loadData = store => {
  return store.dispatch(actions.getRecord(this.props.match.params.id));
};

export default {
  component: Test,
  loadData: loadData
}

这里的问题是 this.props.match.params.id 是未定义的,特别是在 props 部分。我知道这是因为我不在组件内部,如何从其中的 URL 访问参数?

万一这有帮助,我也会展示我的 SSR 部分:

import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { renderRoutes } from 'react-router-config';
import serialize from 'serialize-javascript';
import { Helmet } from 'react-helmet';
import { matchRoutes } from 'react-router-config';

import routes from './src/routes';
import createStore from './src/stores';

function handleRender(req, res) {
  const store = createStore.configure(null); // create Store in order to get data from redux

  const promises = matchRoutes(routes, req.path)
    .map(({ route }) => {
      // Matches the route and loads data if loadData function is there
      return route.loadData ? route.loadData(store) : null;
    })
    .map(promise => {
      if (promise) {
        return new Promise((resolve, reject) => {
          promise.then(resolve).catch(resolve); // lets all data load even if route fails
        });
      }
    });

  Promise.all(promises).then(() => {
    const context = {};
    if (context.url) {
      return res.redirect(301, context.url); // redirect for non auth users
    }

    if (context.notFound) {
      res.status(404); // set status to 404 for unknown route
    }

    const content = renderToString(
      <Provider store={store}>
        <StaticRouter location={req.path} context={context}>
          <div>{renderRoutes(routes)}</div>
        </StaticRouter>
      </Provider>
    );

    const initialState = serialize(store.getState());

    const helmet = Helmet.renderStatic();

    res.render('index', { content, initialState, helmet });
  });
}

module.exports = handleRender;

每个 matchRoutes 项中都有一个 match 属性,您可以将其传递到 loadData 函数中:

matchRoutes(routes, req.path)
    .map(({ route, match }) => {
      return route.loadData ? route.loadData(store, match) : Promise.resolve(null);
    })

然后您的 loadData 函数可以访问它:

const loadData = (store, match) => store.dispatch(reduxAction(match.params.id))