You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It uses getStaticProps to deliver a statically-generated version of the article. That way search engines and people with javascript disabled can see the content.
There may be new comments or reactions since the last time Next.js ran getStaticProps, so React hydrates the page on the client and we re-render with the latest version of the data fetched from OneGraph.
Our getStaticProps function runs the query for the article and serializes the Relay environment to JSON, which is what gets used to statically render the page.
Then we put the initialRecords into the environment when we hydrate the page on the client.
exportconstArticle=({issueNumber, initialRecords})=>{constenvironment=useRelayEnvironment();// Only add cached records on initial renderReact.useMemo(()=>{if(initialRecords){environment.getStore().publish(newRecordSource(initialRecords));}},[initialRecords]);constdata=useLazyLoadQuery(articleQuery,{issueNumber},// store-and-network will populate `data` with records from the store and// fetch new data from the network in the background{fetchPolicy: 'store-and-network'},);return<Articleissue={data.gitHub.repository.issue}/>};
The 'store-and-network'fetchPolicy tells Relay to render with data from the store initially, then send off a network request to get the latest data.
Relay won’t tell you if the data that you’re rendering with is from the network or from the cache. It’s a difficult problem for Relay to solve generally. In many cases, it’s not even clear what it means for data to be cached. Relay has a central store that all queries add data to. It would be difficult and expensive to keep track of the provenance of every piece of data in the store.
For our use-case, the question is more straightforward. Was the data added to the store by publishing our cached initialRecords, or through the fetch that useLazyLoadQuery initiated?
We can answer that question by leveraging client-only fields and custom handlers.
Client-only fields
Relay allows you to extend your server schema with client-only fields. This is typically used for local state management, and can replace tools like redux depending on the use case.
We’ll add a client-only field to the GitHubIssue type by extending the type in a new file called src/clientSchema.graphl.
extendtypeGitHubIssue{isClientFetched: Boolean}
Then we’ll add the field to our query and specify that it should use a custom handler with the @__clientField directive
The @__clientField directive takes a handle argument, which is just a string we will use to determine which handler to use.
Custom handlers
Handlers are extension points that allow for custom logic to add data to the store. Relay has default handlers built-in to deal with things like Connection types, a pattern many GraphQL services use for pagination.
We’ll write our own handler for isClientFetched and use it when we construct the environment, with a fallback to the default handler:
import{DefaultHandlerProvider}from'relay-runtime';constisClientFetchedHandler={update(store/*: RecordSourceProxy */,payload/*: HandleFieldPayload*/){constrecord=store.get(payload.dataID);if(!record)return;constisClient=typeofwindow!=='undefined';// value first, then key. Confusing, but I'm sure there's a good reason for itrecord.setValue(isClient,payload.handleKey);},};functionhandlerProvider(handle/*: string */)/*: Handler */{switch(handle){case'isClientFetched':
returnisClientFetchedHandler;default:
returnDefaultHandlerProvider(handle);}}constenvironment=newEnvironment({
handlerProvider,network: Network.create(fetchQuery)});
The handler will run when a fetch, like the one triggered by useLazyLoadQuery , adds data to the store, but not when we add records directly to the store with store.publish.
On the server, the isClientFetched field will be set to false. It will only become true when we fetch the query on the client.
The full code for this is in the OneBlog repo. We use isClientFetched on OneBlog to determine if we should show a welcome page to the author before they have published any articles.
You can deploy your own blog backed by GitHub issues on Vercel.
The text was updated successfully, but these errors were encountered:
is there a performance difference between commitPayload & environment.getStore().publish() seems like with publish i am calling the network more frequently
This article is really a GitHub issue that was fetched by Relay through OneGraph and turned into an article by Next.js
It uses
getStaticProps
to deliver a statically-generated version of the article. That way search engines and people with javascript disabled can see the content.There may be new comments or reactions since the last time Next.js ran
getStaticProps
, so React hydrates the page on the client and we re-render with the latest version of the data fetched from OneGraph.Our
getStaticProps
function runs the query for the article and serializes the Relay environment to JSON, which is what gets used to statically render the page.Then we put the initialRecords into the environment when we hydrate the page on the client.
The
'store-and-network'
fetchPolicy
tells Relay to render with data from the store initially, then send off a network request to get the latest data.Relay won’t tell you if the data that you’re rendering with is from the network or from the cache. It’s a difficult problem for Relay to solve generally. In many cases, it’s not even clear what it means for data to be cached. Relay has a central store that all queries add data to. It would be difficult and expensive to keep track of the provenance of every piece of data in the store.
For our use-case, the question is more straightforward. Was the data added to the store by publishing our cached
initialRecords
, or through the fetch thatuseLazyLoadQuery
initiated?We can answer that question by leveraging client-only fields and custom handlers.
Client-only fields
Relay allows you to extend your server schema with client-only fields. This is typically used for local state management, and can replace tools like redux depending on the use case.
We’ll add a client-only field to the
GitHubIssue
type by extending the type in a new file calledsrc/clientSchema.graphl
.Then we’ll add the field to our query and specify that it should use a custom handler with the
@__clientField
directiveThe
@__clientField
directive takes ahandle
argument, which is just a string we will use to determine which handler to use.Custom handlers
Handlers are extension points that allow for custom logic to add data to the store. Relay has default handlers built-in to deal with things like
Connection
types, a pattern many GraphQL services use for pagination.We’ll write our own handler for
isClientFetched
and use it when we construct the environment, with a fallback to the default handler:The handler will run when a fetch, like the one triggered by
useLazyLoadQuery
, adds data to the store, but not when we add records directly to the store withstore.publish
.On the server, the
isClientFetched
field will be set to false. It will only become true when we fetch the query on the client.The full code for this is in the OneBlog repo. We use
isClientFetched
on OneBlog to determine if we should show a welcome page to the author before they have published any articles.You can deploy your own blog backed by GitHub issues on Vercel.
The text was updated successfully, but these errors were encountered: