I'm trying to migrate to v4 of React Router and I'm stuck with the prefetch data. The latests versions we used to have match function.
One of the returning parameters was renderProps but now I can't use match so I don't know how to prefetch data. The documentation shows how to load data but doesn't works for me because I'm using the new version of react-router-redux to sync the store.
Here's the code the client:
return (
<MuiThemeProvider muiTheme={letgoMuiTheme}>
<Provider store={store}>
<IntlProvider>
{ routes(history, store) }
</IntlProvider>
</Provider>
</MuiThemeProvider>
);
Routes:
export default function routes(history) {
return (
<ConnectedRouter history={history}>
<Switch>
<Route exact path="/" component={App} />
<Route path="/:lang/chat" component={Chat} />
...
<Route path="*" component={NotFound} status={404} />
</Switch>
</ConnectedRouter>
);
}
Server:
if (context.url) {
res.redirect(302, redirectLocation.pathname + redirectLocation.search);
} else {
const render = () => {
const body = renderToString(
<StaticRouter
location={req.url}
context={context}
>
<MuiThemeProvider muiTheme={muiTheme}>
<Provider store={store}>
<IntlProvider>
{ routes(history, store) }
</IntlProvider>
</Provider>
</MuiThemeProvider>,
</StaticRouter>
);
res.setHeader('content-language', locale);
res.render('index', {
head,
body,
locale,
state: stringState,
...
});
};
Promise.all(
prefetchData(renderProps, store),
)
.then(render)
.catch(prefetchError => next(prefetchError));
}
That's my old server file:
match({ history, routes, location: req.url }, (error, redirectLocation, renderProps) => {
if (error) {
throw error;
} else if (redirectLocation) {
res.redirect(302, redirectLocation.pathname + redirectLocation.search);
} else if (renderProps) {
// Render react components once store is initializaed and return HTTP response
const render = () => {
const body = renderToString(
<MuiThemeProvider muiTheme={muiTheme}>
<Provider store={store}>
<IntlProvider>
<RouterContext {...renderProps} />
</IntlProvider>
</Provider>
</MuiThemeProvider>,
);
res.setHeader('content-language', locale);
res.render('index', {
head,
newrelicScript,
body,
locale,
state: stringState,
...
});
};
// Fetch components data and render HTML (no matter the fetch results
// we need to render something)
Promise.all(
prefetchData(renderProps, store),
)
.then(render)
.catch(prefetchError => next(prefetchError));
} else {
logger.warning('Ops !!! We should never arrive here :(');
next();
}
});
And prefetch data:
export const prefetchData = (renderProps, store) => {
const { components, params } = renderProps;
const { dispatch } = store;
const state = store.getState();
const extractWrappedComponent = (component) => {
if (component.WrappedComponent) {
return extractWrappedComponent(component.WrappedComponent);
}
return component;
};
return components
.filter(component => component !== undefined)
// Get component, be aware if they are wrapped by redux connect or intl.
.map(component => extractWrappedComponent(component))
// Get the fetchData method of each component
.map(component => component.fetchData)
.filter(fetchData => fetchData !== undefined)
// Invoke each fetchData to initialize the redux state.
.map(fetchData => fetchData(state, dispatch, params));
};