Open taion opened 7 years ago
After playing around I was able to get it working (non-hooks version) in Next.js with the following technique:
On the server I do:
await fetchQuery
const records = environment.getStore().getSource()
App.getInitialProps
(didn't work if passed just like an object!)App.render
do JSON.parse
of the stringified records and create const source = new RecordSource(records)
QueryRenderer
that has dataFrom = "STORE_THEN_NETWORK"
This would provide props that are not null
on the client
However! Props would remain null on the server
In order to solve that I took a piece of code from https://github.com/relay-tools/relay-query-lookup-renderer/blob/a9a4ed636a862ff48d8aaf0719aa29c3dfaf86aa/src/index.js#L113
await fetchQuery(
environment,
initialProps.gqlQuery,
initialProps.gqlVariables
)
const records = environment.getStore().getSource() stringifiedRecords = JSON.stringify(records)
const operation = createOperationDescriptor( getRequest(initialProps.gqlQuery), initialProps.gqlVariables ) const snapshot = environment.lookup(operation.fragment, operation) initialProps.gqlResponse = snapshot.data
And the `QueryRenderer` looks like the following:
<QueryRenderer
console.log('props', !!props)
console.log('response', !!gqlResponse)
if (error) {
return null
} else if (data) {
return <Feed data={data} />
} else {
return null
}
}}
/>
I get the following logs:
+ server
props false response true
+ client
props true response true
Changing `dataFrom` to `"NETWORK_ONLY"` results in the same output for the client and server:
props false response true
You can try something like this, rendering ReactRelayContext.Provider
instead of rendering a <QueryRenderer>
.
// on server fetch data
const data = await fetchQuery(
environment,
initialProps.gqlQuery,
initialProps.gqlVariables
)
// on client
const operation = createOperationDescriptor(
getRequest(initialProps.gqlQuery),
initialProps.gqlVariables
)
const data = environment.lookup(operation.fragment, operation).data;
// server and client
<ReactRelayContext.Provider value={{environment}}>
<Feed data={data} />
</ReactRelayContext.Provider>
@robrichard this works like a charm!
pretty sure, that the problems here are solved with this PR https://github.com/facebook/relay/pull/2883
@wasd171 any chance you could share a working example?
@wasd171 how did you get this not to blow out of control over time, or is the source, store and environment re-created per request?
const records = environment.getStore().getSource() stringifiedRecords = JSON.stringify(records)
@robrichard do you have a wrapper component that handle this behavior different on server vs on client?
I've wrote a blog post how I make Relay work well with SSR
https://dev.to/sibelius/adding-server-side-rendering-to-a-relay-production-app-30oc https://medium.com/@sibelius/adding-server-side-rendering-to-a-relay-production-app-8df64495aebf
anybody wanna take a stab to add this to the official docs?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Here is yet another example of how to hydrate/dehydrate Relay store at CDN edge locations using Cloudflare Workers.
https://github.com/kriasoft/nodejs-api-starter/pull/277 See web/main.ts
, web/core/router.ts
, web/proxy/index.ts
, web/proxy/transform.ts
.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This is sort of a follow-up to https://github.com/facebook/relay/issues/1687 and https://github.com/facebook/relay/pull/1760.
What is a recommended pattern for handling server-side rendering in a simple request-response paradigm with Relay Modern?
RecordStore
seems to expose capabilities for serializing and deserializing its contents, and I can use a preloadedRecordStore
when building a newEnvironment
, but this is a bit deceptive, since without https://github.com/facebook/relay/pull/1760, my<QueryRenderer>
s will ignore the preloaded records... but this capability must be there for a reason?But thinking about this more, I'm not even sure the approach in #1760 is correct. For a streaming network layer, it seems like it would be wrong to omit sending out the request just because I have preloaded data – instead I'd just want the server to e.g. not send me the initial payload (because I already have it).
Something like the query response cache seems more promising, but the bundled one doesn't really expose hooks for exporting its contents, plus a key/value cache with a TTL isn't exactly the right model here anyway.
Am I missing something?