next-relay-bridge
v2.0.4
Published
Middleware to simplify using Next.js with the Relay GraphQL client
Readme
Next Relay Bridge
Middleware to simplify using Next.js with the Relay GraphQL client.
What is it?
Next Relay Bridge makes it easy to server-side render Next.js pages that rely on Relay data. With the utilities that Next Relay Bridge provides, you can load Relay queries server-side and use the resultant data to initialize your Relay store on the client.
On the server, we await your queries to create the Relay store's initial state. This initial state is sent to the client, which uses it to hydrate the Relay environment's initial store.
On the client, on first app render, we create the client-side Relay environment with the initial data that was sent by the server. The initial page that was requested can use this hydrated store to get its data, so we can render immediately without any data fetches.
On subsequent client-side page navigations, we fetch the data client-side so that you can use Suspense as necessary for progrsesive loading.
Adding to an existing project
Install Next Relay Bridge with
yarn add next-relay-bridgeornpm -i next-relay-bridge.Create a file to initialze Next Relay Bridge. In this example, we'll refer to this file as
"../path/to/bridge".In this file, create the
withAppBridgeandwithPageBridgeutilities that you'll use to interface with the system using thecreateNextRelayBridgefunction. ExportwithAppBridgeandwithPageBridgefrom this file so we can use it in our application.
// path/to/bridge.js
import { createNextRelayBridge } from "next-relay-bridge";
const { withAppBridge, withPageBridge } = createNextRelayBridge({
getServerEnvironment: () => {
/**
* This function should return the Relay environment that we'll use on the server.
*
* @see: /example/relay/serverEnvironment.ts
*/
},
getClientEnvironment: (initialStore) => {
/**
* This function should return the Relay environment that we'll use on the client.
* This environment must initialize it's store with the incoming `initialStore` value
* that this function receives.
*
* @see: /example/relay/clientEnvironment.ts
*/
},
});
export { withAppBridge, withPageBridge };- Wrap your Next.js
_appcomponent withwithAppBridgeas seen below. Your app component will now receive an additionalrelayEnvironmentprop. Pass this to your<RelayEnvironmentProvider>.
import { RelayEnvironmentProvider } from "react-relay/hooks";
import { withAppBridge } from "../path/to/bridge";
function MyApp({ Component, pageProps, relayEnvironment }) {
return (
<RelayEnvironmentProvider environment={relayEnvironment}>
<Component {...pageProps} />
</RelayEnvironmentProvider>
);
}
export default withAppBridge({
AppComponent: MyApp,
});- To use this on a page component, wrap your page component with
withPageBridgeas seen below.withPageBridgetakes an object as its argument whereAppComponentshould be your page component, andgetInitialPropsshould be an async function that returns your page component's initial props.
getInitialProps receives an object as its argument, where context is the Next.js context object, and preloadQuery is an async function that you use to preload any queries that you want to pass to your page component.
import { usePreloadedQuery } from "react-relay";
import { graphql } from "relay-runtime"; //`
import { SafeSuspense } from "next-relay-bridge";
import { withPageBridge } from "../path/to/bridge";
const somePageQuery = graphql`
query somePageQuery {
viewer {
example
}
}
`;
function SomePageContent({
name,
someQueryReference
}) {
const data = usePreloadedQuery(
somePageQuery,
someQueryReference
);
return (
<div>
My name is {name} and my data is: {JSON.stringify(data)}
</div>
);
}
function SomePage(props) {
return (
<SafeSuspense fallback="Loading...">
<SomePageContent {...props} />
</SafeSuspense>
);
}
export default withPageBridge({
PageComponent: SomePage,
getInitialProps: async ({ context, preloadQuery }) => {
// Use the incoming `preloadQuery` function to load queries. You _must_ await these.
const someQueryReference = await preloadQuery(somePageQuery, {});
// Return any initial props that your page component needs. Next Relay Bridge will introspect
// the props and only process props that have been ran through `preloadQuery`.
return {
name: 'Friend',
someQueryReference
}
}
});That's it! When a user navigates to SomePage directly, we'll wait until the queries have resolved before sending the page up to the client. The client will use the server-side data to initialize its store, and you'll be able to display the whole page without any additional data requests.
When navigating to SomePage on the client via client-side routing, the client will fetch the data and your page will suspend while the data is being fetched.
Creating a new Next.js project with Relay and Next Relay Brdige
Detailed instructions coming soon...
Additional features
SafeSuspensenext-relay-bridgeexports aSafeSuspensecomponent that you can use to suspend while data is being fetched on the client. Currently, we can't useReact.Suspenseon the server, so this component wraps its children with aReact.Fragmentif on the server, or aReact.Suspenseif on the client.- If your
SafeSuspensechildren will suspend on the server (something that is not yet yet supported by ReactDOMServer), passSafeSuspenseaclientOnly={true}prop so that it will rendernullon the server.
- Redirects
- If you need to redireect from a page component using
withPageBridge, yourgetInitialPropsfunction can return an object that has aredirectvalue. It should match the shape of{ destination: string, permanent?: boolean | number }. Ifpermanentisfalse, it will be treated as a 307 redirect. Ifpermanentis true, it'll be a 308. You can also passpermanenta redirect status code to set it directly.
- If you need to redireect from a page component using
