Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Role of QueryRenderer in Relay Modern?

So, first a bit of background. I'm a native iOS/Android developer who is now starting my first ever React Native project. It comes with all the benefits and pains of Javascript, but I like it a lot so far :-) I decided to also try my hand at GraphQL for the first time as well.

Being new to the React milieu in general, I also don’t have any prior knowledge of Relay, but chose it on recommendation from friends in my startup community and my web-dev colleagues. I was also warned about a somewhat steep learning curve, but decided to go ahead anyway - I am already fighting an uphill battle with JS and a 0.xx version of a new mobile platform, so what the hell, right? :-) I managed to set up my project correctly and punch a whole through to my GQL server with a QueryRenderer, which was a great relief :-)

So, on to the questions

I'm having a hard time figuring out the container/component relationship, and container composition in general. Reading the docs on composition helped, but I'm still in doubt over the role of the QueryRenderer

  • QueryRenderer is said by the docs to be the root container for every Relay tree. Does that mean that one should have a QueryRenderer for the root in our app? Or at the root of each navigation path (i.e. tabs in our app)? Or just for each container component (as opposed to presentational/dumb/pure components, React wise)? Note that I'm not looking for opinions, but arguments for best practice :-)
  • Can a FragmentContainer (or any other container, for that matter) work without a QueryRenderer in the ‘parent’ component?
  • How is the QueryRenderer linked to child containers? Does it fetch the sum of all the data that child containers want, and then the child containers read from the cache, or? If so, I’ve misunderstood the pros of Relay - we are under the impression that each component can retrieve data independently from every other components, and that each component does not know anything about the data requirements of other components (including parent/child components). I think this assumption is also what confuses me about the QueryRenderer, and the need for a “Root” container.
  • If QueryRenderer is a ‘parent’/‘root’ Relay container to a Relay tree, how come it has to render view components based on it’s request? And why does it have to have a request? When and for what should we use a QueryRenderer?

Any help is much appreciated :-)

like image 966
jhm Avatar asked May 18 '17 11:05

jhm


1 Answers

So, after having worked some more with our app, I thought I'd come back to post about our thoughts and experiences so far, in the hopes that it helps someone.

Building on @Peter Suwara's great post, we arrived at a similar strategy initially

  • Have a root/parent nav tree
  • For each screen in the tree, have a QueryRenderer as the root for all presentational/dumb components it contains
  • Use fragments to declare data dependencies within the subcomponents

Like we discussed in the comments below his answer though, this approach might not always be the best. After further discussion internally, we came to the conclusion that there are too many cases where this might not make sense after all for a couple of reasons:

  • If you retrieve data for each screen-load, you often times will end up with more roundtrips than necessary. You want to take the app-flow into account, and fetch as much data as is viable/needed for a route and it's children.
  • Also, if you retrieve all data for the child components of a screen on the same QueryRenderer, you might sometimes end up fetching data that will never be shown to the user (i.e. details for a details view that is rarely shown, or similar cases).

After some more thought and discussion, we came up with this rule-of-thumb for when to create a new QueryRenderer 'root' of a Relay tree:

Create a new QueryRenderer for whenever you need a new error-handling strategy

This occured for the very practical reason that it's the only chance you have to handle errors/loading of data, but it also made sense to us in the way of user-flow and composition, as usually the two things collide - you want a new way of handling network errors when you reach a new 'flow'/part of your app. Maybe some smarter heads at Facebook thought about this before us? :-)

As with all rules of thumb, it's just that - a guideline, and not a rule, and it has exceptions, of course. However, it seems to make sense for us internally - at least for now.

Any and all feedback on these thoughts are very welcome, as I think the official docs are lackluster to say the least, and community discussion is therefore all we have until the docs and general patterns are settled upon with time.

like image 198
jhm Avatar answered Oct 09 '22 04:10

jhm