Next.js: Example with-relay-modern incompatible with Relay 2.0.0

Created on 28 Jan 2019  路  3Comments  路  Source: vercel/next.js

The example with-relay-modern works, but when the react-relay is updated from 1.5.0 to 2.0.0, using GraphQL queries with fragments give this error:

{ Invariant Violation: Relay(TopicList) tried to render a context that was not valid this means that Relay(TopicList) was rendered outside of a query renderer.
    at invariant (/Users/.../node_modules/fbjs/lib/invariant.js:40:15)
    at Object.forwardRef [as render] (/Users/.../node_modules/react-relay/lib/buildReactRelayContainer.js:59:85)
    at ReactDOMServerRenderer.render (/Users/.../node_modules/react-dom/cjs/react-dom-server.node.development.js:3205:44)
...

I think this error could be caused by this change in 2.0.0:

Relay now uses new Context API instead of Legacy Context API. Any consumers of Relay context using the Legacy context API will break.

(see https://github.com/facebook/relay/releases)

Most helpful comment

So it looks that the fix for react-relay 1.5.0 -> 2.0.0 is pretty simple. In lib/withData.js:

 import React from 'react'
-import { fetchQuery } from 'react-relay'
+import { fetchQuery, ReactRelayContext } from 'react-relay'
 import initEnvironment from './createRelayEnvironment'
-import RelayProvider from './RelayProvider'

 export default (ComposedComponent, options = {}) => {
   return class WithData extends React.Component {
@@ -52,9 +51,9 @@ export default (ComposedComponent, options = {}) => {

     render () {
       return (
-        <RelayProvider environment={this.environment} variables={{}}>
+        <ReactRelayContext.Provider value={{ environment: this.environment, variables: {} }}>
           <ComposedComponent {...this.props} />
-        </RelayProvider>
+        </ReactRelayContext.Provider>
       )
     }
   }

The file lib/RelayProvider.js is not used anymore and can be removed.

I will try to send a pull request tomorrow.

All 3 comments

So it looks that the fix for react-relay 1.5.0 -> 2.0.0 is pretty simple. In lib/withData.js:

 import React from 'react'
-import { fetchQuery } from 'react-relay'
+import { fetchQuery, ReactRelayContext } from 'react-relay'
 import initEnvironment from './createRelayEnvironment'
-import RelayProvider from './RelayProvider'

 export default (ComposedComponent, options = {}) => {
   return class WithData extends React.Component {
@@ -52,9 +51,9 @@ export default (ComposedComponent, options = {}) => {

     render () {
       return (
-        <RelayProvider environment={this.environment} variables={{}}>
+        <ReactRelayContext.Provider value={{ environment: this.environment, variables: {} }}>
           <ComposedComponent {...this.props} />
-        </RelayProvider>
+        </ReactRelayContext.Provider>
       )
     }
   }

The file lib/RelayProvider.js is not used anymore and can be removed.

I will try to send a pull request tomorrow.

Thanks!

It is possible to use Relay Modern, in a standard way as per the Relay documentation, in Next.js by not using _ssr_ for the renderer import:

const Renderer = dynamic( () => import('../../components/relay/Renderer'), { loading: () => <p>loading ...</p>, ssr: false } )

Was this page helpful?
0 / 5 - 0 ratings