2

I am pretty positive why this won't work, but I'm not sure how to fix it.

I have a component which uses a loadData() function at the end in order to pass data through to the store to be SSR.

An example component would be something like

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
}

The problem here is that this.props.match.params.id is undefined, particularly at the props part. I know this is because I am not inside the component, how do I access the params from the URL inside this?

Just incase this helps I will show my SSR part as well:

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;

1 Answer 1

4

There is a match property within each matchRoutes item, which you can pass into your loadData function:

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

Your loadData function can then access it:

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

Sign up to request clarification or add additional context in comments.

1 Comment

I have done this already, but forgot to put the answer haha, thanks for answering this ill accept!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.