4.0.0-beta.4
I am trying to use react-router in the server and In v4-alpha I would use createServerRenderContext, which I think this has been removed from v4-beta, is that correct? if so, how would i now do the following?
const context = createServerRenderContext();
I was thinking this is now simply react context when using a component (i.e. this.context), but am not sure.
The new docs for StaticRouter do mention context, but do not mention how to create it. Later they do mention router.context, but as the router hasn't been created yet, i guess it isn't this?
The context is now just an object.
const context = {}
renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
)
thanks for clearing that up
hi,
Is there some way I can get object like renderProps in v3?
that can get static method of each component ?
do some thing like prepare redux in the server side.
@uniz if i read your question right, you have components which contain a static method for fetching data, probably redux actions?
if so, this is how i handle it; i have created a middleware on the server to match the req.url against the routes. If the matching path has a component with a static method of 'needs' (as in _needs data_. feel free to come up with a better name!) then i use the store to dispatch the method.
_note: the getMatch function isn't very sophisticated - i expect i could be improved somewhat to match multiple paths or nested paths etc_
// middleware/set-router-context.js
import React from 'react';
import { renderToString } from 'react-dom/server';
import StaticRouter from 'react-router-dom/StaticRouter';
import { Provider } from 'react-redux';
import matchPath from 'react-router-dom/matchPath'
import configureStore from '../../app/store/configure-store';
import { makeRoutes, routes } from '../../app/routes';
function getMatch(url) {
return routes
.find((route) => matchPath(url, route.path, { exact: true, strict: false }))
}
async function getData(dispatch, req) {
const needs = [];
routes
.filter((route) => route.component.needs)
.map((route) => {
const match = getMatch(req.url);
if (match){
route.component.needs.map((need) => needs.push(dispatch(need(match.params))))
}
});
await Promise.all(needs);
}
class Markup extends React.Component {
render() {
const { req,store } = this.props;
return (
<Provider store={store}>
<StaticRouter location={req.url} context={{}} >
{makeRoutes()}
</StaticRouter>
</Provider>
)
}
}
function setRouterContext() {
return async (ctx, next) => {
const store = configureStore();
const markup = renderToString(<Markup req={ ctx.request } store={store} />);
await getData(store.dispatch, ctx.request);
const match = getMatch(ctx.request.url);
ctx.status = match ? 200 : 404;
ctx.initialState = store.getState();
ctx.markup = markup;
await next();
};
}
export default setRouterContext;
// server.js
...
app.use(setRouterContext())
I don't think it'll be final solution, but its a direct translation from how i was handling it in react-router v2. I think v4 will enable better solutions to present themselves once i get use to the _new_ way of doing things in rr
@peter-mouland mutch thanks
English is important for me~
Most helpful comment
The context is now just an object.