diff --git a/examples/with-relay-modern/.env b/examples/with-relay-modern/.env
index d8a2a35d5119cd..01cf99e71fcebd 100644
--- a/examples/with-relay-modern/.env
+++ b/examples/with-relay-modern/.env
@@ -1 +1 @@
-RELAY_ENDPOINT=https://api.graph.cool/relay/v1/next-js-with-relay-modern-example
+NEXT_PUBLIC_RELAY_ENDPOINT=https://api.graph.cool/relay/v1/next-js-with-relay-modern-example
diff --git a/examples/with-relay-modern/README.md b/examples/with-relay-modern/README.md
index 65fbf2d087951f..ed6ed9a9694356 100644
--- a/examples/with-relay-modern/README.md
+++ b/examples/with-relay-modern/README.md
@@ -2,8 +2,6 @@
[Relay Modern](https://relay.dev/) is a new version of Relay designed from the ground up to be easier to use, more extensible and, most of all, able to improve performance on mobile devices. Relay Modern accomplishes this with static queries and ahead-of-time code generation.
-In this simple example, we integrate Relay Modern seamlessly with Next by wrapping our _pages_ inside a [higher-order component (HOC)](https://facebook.github.io/react/docs/higher-order-components.html). Using the HOC pattern we're able to pass down a query result data created by Relay into our React component hierarchy defined inside each page of our Next application. The HOC takes `options` argument that allows to specify a `query` that will be executed on the server when a page is being loaded.
-
This example relies on [graph.cool](https://www.graph.cool) for its GraphQL backend.
## Deploy your own
diff --git a/examples/with-relay-modern/components/BlogPostPreview.js b/examples/with-relay-modern/components/BlogPostPreview.js
index 7e1324e58dd877..4988b2290312dc 100644
--- a/examples/with-relay-modern/components/BlogPostPreview.js
+++ b/examples/with-relay-modern/components/BlogPostPreview.js
@@ -1,4 +1,3 @@
-import React from 'react'
import { createFragmentContainer, graphql } from 'react-relay'
const BlogPostPreview = ({ post }) =>
{post.title}
diff --git a/examples/with-relay-modern/components/BlogPosts.js b/examples/with-relay-modern/components/BlogPosts.js
index 834b5971d8749b..2cd0b78a0e0ebb 100644
--- a/examples/with-relay-modern/components/BlogPosts.js
+++ b/examples/with-relay-modern/components/BlogPosts.js
@@ -1,4 +1,3 @@
-import React from 'react'
import { createFragmentContainer, graphql } from 'react-relay'
import BlogPostPreview from './BlogPostPreview'
diff --git a/examples/with-relay-modern/lib/createRelayEnvironment.js b/examples/with-relay-modern/lib/createRelayEnvironment.js
deleted file mode 100644
index d152c0d44e13e8..00000000000000
--- a/examples/with-relay-modern/lib/createRelayEnvironment.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import { Environment, Network, RecordSource, Store } from 'relay-runtime'
-
-let relayEnvironment = null
-
-// Define a function that fetches the results of an operation (query/mutation/etc)
-// and returns its results as a Promise:
-function fetchQuery(operation, variables, cacheConfig, uploadables) {
- return fetch(process.env.RELAY_ENDPOINT, {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-Type': 'application/json',
- }, // Add authentication and other headers here
- body: JSON.stringify({
- query: operation.text, // GraphQL text from input
- variables,
- }),
- }).then((response) => response.json())
-}
-
-export default function initEnvironment({ records = {} } = {}) {
- // Create a network layer from the fetch function
- const network = Network.create(fetchQuery)
- const store = new Store(new RecordSource(records))
-
- // Make sure to create a new Relay environment for every server-side request so that data
- // isn't shared between connections (which would be bad)
- if (typeof window === 'undefined') {
- return new Environment({
- network,
- store,
- })
- }
-
- // reuse Relay environment on client-side
- if (!relayEnvironment) {
- relayEnvironment = new Environment({
- network,
- store,
- })
- }
-
- return relayEnvironment
-}
diff --git a/examples/with-relay-modern/lib/relay.js b/examples/with-relay-modern/lib/relay.js
new file mode 100644
index 00000000000000..4f91b008a6b10f
--- /dev/null
+++ b/examples/with-relay-modern/lib/relay.js
@@ -0,0 +1,50 @@
+import { useMemo } from 'react'
+import { Environment, Network, RecordSource, Store } from 'relay-runtime'
+
+let relayEnvironment
+
+// Define a function that fetches the results of an operation (query/mutation/etc)
+// and returns its results as a Promise
+function fetchQuery(operation, variables, cacheConfig, uploadables) {
+ return fetch(process.env.NEXT_PUBLIC_RELAY_ENDPOINT, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ }, // Add authentication and other headers here
+ body: JSON.stringify({
+ query: operation.text, // GraphQL text from input
+ variables,
+ }),
+ }).then((response) => response.json())
+}
+
+function createEnvironment(initialRecords) {
+ return new Environment({
+ // Create a network layer from the fetch function
+ network: Network.create(fetchQuery),
+ store: new Store(new RecordSource()),
+ })
+}
+
+export function initEnvironment(initialRecords) {
+ // Create a network layer from the fetch function
+ const environment = relayEnvironment ?? createEnvironment(initialRecords)
+
+ // If your page has Next.js data fetching methods that use Relay, the initial records
+ // will get hydrated here
+ if (initialRecords) {
+ environment.getStore().publish(new RecordSource(initialRecords))
+ }
+ // For SSG and SSR always create a new Relay environment
+ if (typeof window === 'undefined') return environment
+ // Create the Relay environment once in the client
+ if (!relayEnvironment) relayEnvironment = environment
+
+ return relayEnvironment
+}
+
+export function useEnvironment(initialRecords) {
+ const store = useMemo(() => initEnvironment(initialRecords), [initialRecords])
+ return store
+}
diff --git a/examples/with-relay-modern/lib/withData.js b/examples/with-relay-modern/lib/withData.js
deleted file mode 100644
index 9dd27fecda84c6..00000000000000
--- a/examples/with-relay-modern/lib/withData.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import React from 'react'
-import initEnvironment from './createRelayEnvironment'
-import { fetchQuery, ReactRelayContext } from 'react-relay'
-
-export default function withData(ComposedComponent, options = {}) {
- return class WithData extends React.Component {
- static displayName = `WithData(${ComposedComponent.displayName})`
-
- static async getInitialProps(ctx) {
- // Evaluate the composed component's getInitialProps()
- let composedInitialProps = {}
- if (ComposedComponent.getInitialProps) {
- composedInitialProps = await ComposedComponent.getInitialProps(ctx)
- }
-
- let queryProps = {}
- let queryRecords = {}
- const environment = initEnvironment()
-
- if (options.query) {
- // Provide the `url` prop data in case a graphql query uses it
- // const url = { query: ctx.query, pathname: ctx.pathname }
- const variables = {}
- // TODO: Consider RelayQueryResponseCache
- // https://github.com/facebook/relay/issues/1687#issuecomment-302931855
- queryProps = await fetchQuery(environment, options.query, variables)
- queryRecords = environment.getStore().getSource().toJSON()
- }
-
- return {
- ...composedInitialProps,
- ...queryProps,
- queryRecords,
- }
- }
-
- constructor(props) {
- super(props)
- this.environment = initEnvironment({
- records: props.queryRecords,
- })
- }
-
- render() {
- return (
-
-
-
- )
- }
- }
-}
diff --git a/examples/with-relay-modern/next.config.js b/examples/with-relay-modern/next.config.js
deleted file mode 100644
index 12aabac545184c..00000000000000
--- a/examples/with-relay-modern/next.config.js
+++ /dev/null
@@ -1,22 +0,0 @@
-require('dotenv').config()
-
-const path = require('path')
-const Dotenv = require('dotenv-webpack')
-
-module.exports = {
- webpack: (config) => {
- config.plugins = config.plugins || []
-
- config.plugins = [
- ...config.plugins,
-
- // Read the .env file
- new Dotenv({
- path: path.join(__dirname, '.env'),
- systemvars: true,
- }),
- ]
-
- return config
- },
-}
diff --git a/examples/with-relay-modern/package.json b/examples/with-relay-modern/package.json
index 3dce58a477cb5d..4c18737b706ee0 100644
--- a/examples/with-relay-modern/package.json
+++ b/examples/with-relay-modern/package.json
@@ -1,7 +1,7 @@
{
"name": "with-relay-modern",
- "version": "3.0.4",
- "description": "Example of Next.js with Relay Modern SSR",
+ "version": "1.0.0",
+ "description": "Example of Next.js with Relay Modern",
"scripts": {
"graphcool-init": "graphcool init --schema schema/init-schema.graphql",
"dev": "next",
@@ -10,11 +10,8 @@
"relay": "relay-compiler --src ./ --exclude '**/.next/**' '**/node_modules/**' '**/test/**' '**/__generated__/**' --exclude '**/schema/**' --schema ./schema/schema.graphql",
"schema": "graphql get-schema -e dev"
},
- "author": "",
"license": "ISC",
"dependencies": {
- "dotenv": "^8.2.0",
- "dotenv-webpack": "^1.7.0",
"graphql": "^14.6.0",
"next": "latest",
"react": "^16.13.0",
diff --git a/examples/with-relay-modern/pages/_app.js b/examples/with-relay-modern/pages/_app.js
new file mode 100644
index 00000000000000..838595f393e651
--- /dev/null
+++ b/examples/with-relay-modern/pages/_app.js
@@ -0,0 +1,12 @@
+import { ReactRelayContext } from 'react-relay'
+import { useEnvironment } from '../lib/relay'
+
+export default function App({ Component, pageProps }) {
+ const environment = useEnvironment(pageProps.initialRecords)
+
+ return (
+
+
+
+ )
+}
diff --git a/examples/with-relay-modern/pages/about.js b/examples/with-relay-modern/pages/about.js
new file mode 100644
index 00000000000000..3b24db70d99634
--- /dev/null
+++ b/examples/with-relay-modern/pages/about.js
@@ -0,0 +1,12 @@
+import Link from 'next/link'
+
+export default function About() {
+ return (
+