-
Notifications
You must be signed in to change notification settings - Fork 26.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Relay Modern example #1757
Comments
I continued working on it in the repo I created when I was trying to get Relay-Antique to work with Next: https://github.com/Gregoor/next.js-relay-example Unfortunately I'm currently stuck with this issue: facebook/relay#1631 |
That particular issue is solved for now, but it's still not there yet. Haven't quite figured out how to get the Environment to accept my hydration. @josephsavona's comment about the possibility of SSR seems more like a description of a better future, as of right now |
@Gregoor Hydration of the environment is straightforward but not documented: the RecordSource object has a toJSON() method, the result of which can be passed back to the constructor to rehydrate. |
The larger blocker for SSR is that by default the QueryRenderer and network layer do not read from cache and always effectively force-fetch. i would take a look at how QueryRenderer works, and create a variation that supports SSR. |
@Gregoor @josephsavona - As a short term solution to server side rendering for relay modern specifically in next.js... (WIP, don't judge the code too much). I have a HOC called NextPage that does some generic setup for all our pages: import React, { Component } from 'react';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import materialTheme from '../lib/materialTheme';
import environment from '../lib/relayEnvironment';
export default query => ComposedComponent => class NextPage extends Component {
static async getInitialProps(ctx) {
const { req } = ctx;
const isServer = !!req;
const userAgent = req ? req.headers['user-agent'] : navigator.userAgent;
let pageProps = {};
if (query) {
const {
createOperationSelector,
getOperation,
} = environment.unstable_internal;
const operation = createOperationSelector(getOperation(query));
const result = await new Promise((resolve) => environment.streamQuery({
operation,
onNext: () => resolve(environment.lookup(operation.fragment).data),
}));
pageProps = {
...result,
};
if (isServer) pageProps.recordSource = environment.getStore().getSource().toJSON();
}
if (ComposedComponent.getInitialProps) {
pageProps = {
...await ComposedComponent.getInitialProps(ctx),
};
}
return {
...pageProps,
// initialState: store.getState(),
isServer,
userAgent,
};
}
render () {
const { userAgent } = this.props;
return (
<MuiThemeProvider muiTheme={getMuiTheme(materialTheme, { userAgent })}>
<ComposedComponent {...this.props} />
</MuiThemeProvider>
)
}
}; Then in my page, import React, { Component } from 'react';
import { QueryRenderer, graphql } from 'react-relay';
import environment from '../lib/relayEnvironment';
import NextPage from '../decorators/NextPage';
import Layout from '../containers/Layout';
const query = graphql`
query pagesQuery {
root {
properties {
edges {
node {
id
propertyName
street
}
}
}
}
}
`
class HomePage extends Component {
render() {
return (
<QueryRenderer
environment={environment}
query={query}
render={({error, props}) => {
console.log(error, props);
if (error) {
return <Layout>{error.message}</Layout>;
} else if (props || this.props) {
const serProps = props || this.props;
return (
<Layout>
{serProps.root.properties.edges.map(({ node }) => <p>{node.propertyName}</p>)}
</Layout>
);
}
return <Layout>Loading</Layout>;
}}
/>
);
}
}
export default NextPage(query)(HomePage); This is definitely a workaround, as we are essentially hijacking the render method of QueryRenderer to render the response from getInitialProps instead of props inside the QueryRenderer scope. This workaround is potentially alleviated by facebook/relay#1760 which will add a lookup prop to QueryRenderer. Also you'll see in my HOC if we are on the server i'm adding recordSource: to the returned props, which will get added into the NEXT_DATA and then i use the value from that to hydrate the store like so: let initial = {};
// Hydrate the store from __NEXT_DATA__
if (typeof window !== 'undefined' && window.__NEXT_DATA__) {
initial = window.__NEXT_DATA__.recordSource;
}
const source = new RecordSource(initial);
const store = new Store(source); |
Hey @brad-decker, thanks for posting that. Unfortunately I'm not getting it to server-render something. If you have the time, could you check if I went wrong somewhere? Here is the repo: |
If anyone is looking for working solution https://github.com/este/este/blob/d959fb96dac5a3e346a2897ae4f2e81a9948ac17/components/app.js Note we are fetching query even for page transition. Next.js + Relay Modern = 😻 Finally, after many years, the developers can write JS apps without annoying spinners everywhere. This is the panacea. As for an implementation. It's based on https://github.com/robrichard/relay-context-provider Thank you! Note it does not support subscriptions, but I think subscriptions don't belong into page query. |
Great work @steida 👍 I've prepared a simple example based on your solution. Comments are welcome 🙂 |
* Add examples/with-redux-code-splitting. (#2721) * #1757 Relay Modern Example (#2696) * Add ReasonML example (#2640) * Add ReasonML example * Add a gitignore specifically for the reasonml example * Allow custom className for <Main /> (#2802) * 3.0.2 * Remove beta information from the README. * 3.0.3 * Remove unnecessary lookup in example with emotion (#2731) * Document SCSS/Less (#2742) * Document SCSS/Less * Add missing word * Add docs for examples dir * Add extra example * uppercase J * Add with pkg example (#2751) * Add custom server micro example (#2750) * Ease running multiple examples at the same time with process.env.PORT (#2753) * Add line-height rule for error page h2 (#2761) * Add support for fetching multiple translation files (#2743) * Add support for fetching multiple translation files * Cleanup * Clear missed interval (#2611) * clear missed interval * remove trailing whitespace * Relay Modern Example (#1757) (#2773) * Simplification of Relay Modern Example (#1757) (#2776) * Use deterministic names for dynamic import (#2788) * Always use the same name for the same dynamic import. * Add unit tests for the modulePath generation. * Allow tests to run correctly on Windows. * Make the chunk name a bit pretty. * Fix tests to run on Windows. * 3.0.4 * Revert "Make the chunk name a bit pretty." (#2792) This reverts commit 0c9e8cf. * 3.0.5 * Use _ as the divider for dynamic import name splitter. (#2793) Using - gives us some weird webpack errors. * 3.0.6 * next/dynamic Error Message Tweaks (#2798) * Fixed issue (#2804) #2800 * docs(material-ui): move the source code to Material-UI repository (#2808)
Unfortunately it doesn't work offline :( |
Can someone close the issue please? |
@steida sure thing 👌 |
Hi @timneutkens , I'm getting this error "Can't load ./cmds plugin:Error: Cannot find module 'graphql-playground/middleware'" with with-relay-modern example. Any idea what's going on? |
Hi, @astenmies I'm not aware that this example would depend on GraphQL Playground. Anyway, there must have been some changes in this package recently. If you are using it in your Express server, this should fix it:
and this:
|
anyone already looking into gettings this to work with React 16? @petrvlcek maybe? Edit: Okay, update was trivial. Created a PR for it #3365 |
With the announcement of Relay Modern, it would be great to assemble an example of Next.js + Relay. According to this @josephsavona's comment it should be possible to have SSR.
The text was updated successfully, but these errors were encountered: