Skip to content

Commit

Permalink
[Examples] Move with-relay-modern to SSG (vercel#13882)
Browse files Browse the repository at this point in the history
Related to vercel#11014
  • Loading branch information
lfades authored and rokinsky committed Jul 11, 2020
1 parent f58ea6e commit 2c21682
Show file tree
Hide file tree
Showing 12 changed files with 97 additions and 134 deletions.
2 changes: 1 addition & 1 deletion 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
2 changes: 0 additions & 2 deletions examples/with-relay-modern/README.md
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion examples/with-relay-modern/components/BlogPostPreview.js
@@ -1,4 +1,3 @@
import React from 'react'
import { createFragmentContainer, graphql } from 'react-relay'

const BlogPostPreview = ({ post }) => <li>{post.title}</li>
Expand Down
1 change: 0 additions & 1 deletion 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'

Expand Down
44 changes: 0 additions & 44 deletions examples/with-relay-modern/lib/createRelayEnvironment.js

This file was deleted.

50 changes: 50 additions & 0 deletions 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
}
54 changes: 0 additions & 54 deletions examples/with-relay-modern/lib/withData.js

This file was deleted.

22 changes: 0 additions & 22 deletions examples/with-relay-modern/next.config.js

This file was deleted.

7 changes: 2 additions & 5 deletions 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",
Expand All @@ -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",
Expand Down
12 changes: 12 additions & 0 deletions 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 (
<ReactRelayContext.Provider value={{ environment, variables: {} }}>
<Component {...pageProps} />
</ReactRelayContext.Provider>
)
}
12 changes: 12 additions & 0 deletions examples/with-relay-modern/pages/about.js
@@ -0,0 +1,12 @@
import Link from 'next/link'

export default function About() {
return (
<div>
<Link href="/">
<a>Home</a>
</Link>
<p>This is the about page</p>
</div>
)
}
24 changes: 20 additions & 4 deletions examples/with-relay-modern/pages/index.js
@@ -1,13 +1,29 @@
import withData from '../lib/withData'
import Link from 'next/link'
import { fetchQuery } from 'react-relay'
import { initEnvironment } from '../lib/relay'
import BlogPosts from '../components/BlogPosts'
import indexPageQuery from '../queries/indexPage'

const Index = ({ viewer }) => (
<div>
<Link href="/about">
<a>About</a>
</Link>
<BlogPosts viewer={viewer} />
</div>
)

export default withData(Index, {
query: indexPageQuery,
})
export async function getStaticProps() {
const environment = initEnvironment()
const queryProps = await fetchQuery(environment, indexPageQuery)
const initialRecords = environment.getStore().getSource().toJSON()

return {
props: {
...queryProps,
initialRecords,
},
}
}

export default Index

0 comments on commit 2c21682

Please sign in to comment.