-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Make RelayRenderer isomorphic #921
Conversation
props: null, | ||
retry: this._retry.bind(this), | ||
stale: false, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd probably just use an if
/else
here rather than a many-line ternary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But isn't it good practice to follow functional programming style when possible? Besides there is even fancier ternary in _runQueries
. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for if/else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a problem, replaced with if/else. But it looks bit bulkier and harder to read, IMHO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for the else
when return
ing conditionally.
a7292c3
to
2980337
Compare
@denvned Can you provide an example of how this would be used to implement server rendering? Would the new As an alternative to this approach, how about creating an "isomorphic" RelayEnvironment implementation to be used as below. You could compose environment instances and override the implementation of key methods - forceFetch, primeCache - to skip work when data was already fetched: // server
var serverEnvironment = new ServerRelayEnvironment(new RelayEnvironment());
React.renderToString(<RelayRender environment={serverEnvironment} ... />
var data = serverEnvironment.getDataForClient(); // <-- return to client
// client
dataFromServer; // from last step of server
var clientEnvironment = new ClientRelayEnvironment(
new RelayEnvironment(),
dataFromServer
);
React.render(<RelayRenderer environment={clientEnvironment} ... /> |
Sure, it mostly follows your recommendations in #589 (comment), and #589 (comment): // server
const environment = new RelayEnvironment();
environment.prepareData(Container, queryConfig).then(
({props, data}) => {
const reactMarkup = ReactDOMServer.renderToString(<RelayRenderer {...props} />);
renderHtmlPage(reactMarkup, JSON.stringify(data));
}
);
// client
const environment = new RelayEnvironment();
const data = JSON.parse(getData());
environment.injectData(Container, queryConfig, data).then(
(props) => {
ReactDOM.render(<RelayRenderer {...props} />, root);
}
); In both cases
We need it on both, because the data should be ready on the client during the initial render, otherwise React wouldn't reuse server-side rendered markup.
Actually, I have already tried that approach but unsuccessfully: #625 (comment). Also I think passing |
2dcb2b2
to
379e596
Compare
I see, thanks for clarifying. You're referring to your comment:
This makes sense - My concern here is that the shape and value of I'd like to see a proposal that uses some form of composition in order to avoid the need to change the To summarize, rather than proceed with this PR I propose that we:
@denvned what do you think? |
I have also been working on a lower-level component that RelayRenderer would compose. I came to the same conclusion as @denvned that feeding in a @denvned Do you want to take a stab at this? Or want me to go ahead and build it (which is what I was planning on doing today)? |
I thought that it could be an undocumented, internals only prop that is passed exclusively as a part of opaque
Nice idea! I think I even see all the details of a possible implementation (probably the trickiest part is to not allow
@yungsters, I can not wait to see it, but would not be able to build it myself today. So please do it! 👍
@josephsavona, I think the first commit of this PR is still useful, it cleans up |
379e596
to
ab93e1a
Compare
I understand this line of thinking, and it's really tempting. Unfortunately if someone can pass it as a prop and depend on its behavior, they will, and this limits our flexibility. I really like @yungsters idea of a lower-level
I would imagine that this new component would render the root component directly at first, until the point that the props have changed and data needs to be fetched from the server. At that point you'd render a
Agree that the first commit is worth discussing on its own; no rush, maybe split that off into a separate PR as time permits? |
@josephsavona I've made a separate PR, #942. |
@yungsters Looks like it should. Thanks! |
The first commit of this PR does refactoring that simplifies state handling, but does not change behaviour. And the second, very simple one, actually makes
RelayRenderer
isomorphic.Now it is possible to pass an
initialReadyState
toRelayRenderer
, allowing server-side rendering and initial rendering in the browser to use pre-primed data.See #589