When using Apollo's SSR implementation with react-router v4 with the following code (in express-context, assuming res was provided bei express) the following error appears:
const context = createServerRenderContext();
const client = new ApolloClient({
ssrMode: true,
networkInterface: createNetworkInterface('http://localhost:3000/graphql', {
credentials: 'same-origin',
headers: req.headers,
}),
});
const app = (<ApolloProvider client={client}>
<ServerRouter
location={req.url}
context={context}
>
<div>
<h1>Hello World!</h1>
<Match pattern="/" exactly render={() => (<span>Home</span>)} />
<Match pattern="/foo" render={() => (<span>Foo</span>)} />
<Match pattern="/bar" render={() => (<span>Bar</span>)} />
<Miss render={() => (<span>Sorry, nothing found =(</span>)} />
</div>
</ServerRouter>
</ApolloProvider>);
getDataFromTree(data.children).then((apolloContext: Object) => {
// this breaks...
}).catch((e: Object) => {
throw new Error(e);
});
Error Message:
TypeError: Cannot set property 'hasMissComponent' of undefined
at Object.registerMissPresence (/Users/Stefan/Documents/www/projects/starterkit/build/server.js:109436:45)
at new Miss (/Users/Stefan/Documents/www/projects/starterkit/build/server.js:107196:30)
at getQueriesFromTree (/Users/Stefan/Documents/www/projects/starterkit/build/server.js:70527:27)
at /Users/Stefan/Documents/www/projects/starterkit/build/server.js:70543:78
at forEachSingleChild (/Users/Stefan/Documents/www/projects/starterkit/build/server.js:66125:10)
at traverseAllChildrenImpl (/Users/Stefan/Documents/www/projects/starterkit/build/server.js:67110:7)
at traverseAllChildrenImpl (/Users/Stefan/Documents/www/projects/starterkit/build/server.js:67126:25)
at traverseAllChildren (/Users/Stefan/Documents/www/projects/starterkit/build/server.js:67205:12)
at Object.forEachChildren [as forEach] (/Users/Stefan/Documents/www/projects/starterkit/build/server.js:66145:5)
at getQueriesFromTree (/Users/Stefan/Documents/www/projects/starterkit/build/server.js:70543:28)
Any idea on how to setup react-router v4 with apollo?
So the error seems to occur because react-apollo's getDataFromTree() calls the render()-Function on the <Miss> Component, as it does with all children to iterate through and detect possible graphql-bindings.
Unfortunately, the <Miss> Component's render Method relies on a variable which is actually set in its componentWillMount, which is too available on the server but for some reason not called by react-apollo's getDataFromTree().
I don't think calling a components render() method without calling its componentWillMount() beforehand is a good idea. In fact, i think it's a really bad idea.
This is very unnatural to react components and can break a lot of things.
@stnwk if you look here we do actualy call componentWillMount() before the render.
What version are you running? Could you open a failing test?
Ah, thanks @jbaxleyiii!
I was still using 0.5.4, the issue was almost resolved by updating to 0.5.5,
but one thing is still missing:
When you look at this specific part in this file:
const Component = new ComponentClass(ownProps, context);
try {
Component.props = ownProps;
Component.setState = (newState: any) => {
Component.state = assign({}, Component.state, newState);
};
} catch (e) {} // tslint:disable-line
ownProps and context get passed on to the ComponentClass Constructor, but since this is not enough to ensure correct rendering ownProps gets once again assigned to Component.props = ownProps but context doesn't, which does not ensure the correct context in pure components which only take props as a parameter, but still manage their context correctly in a "normal rendering process".
So we need to fix one more thing:
Component.context = context; is missing to make my example (react-router v4 implementation) work with apollo-react.
Sidenote:
For someone who is actually looking to make my example work, adding the line as proposed above will not actually make the example work.
It will lead to another issue, which is a problem #3877 in react-router v4 and not in react-apollo. So adding the line only resolves the issue adressed here.
@stnwk great point! I'll add that in for the next release!
Thanks :)
in the next release (going out now!)