Relay: Relay-compiler, types and fragments

Created on 19 Jul 2020  路  5Comments  路  Source: facebook/relay

Simplifying my situation below, but essentially - I have a fragment

fragment Location_details on Location {
    id
    name
    lat
    lon
}

and a query

query AvailableLocationsQuery($query: String) {
    queryCities(query: $query) {
        city
        location {
            ...Location_details
        }
    }
    querySpecialRegions(query: $query) {
        specialRegion
        location {
            ...Location_details
        }
    }
}

So, when given a response type, I want to be able to access response.queryCities.city as well as response.queryCities.location.lat.

However, relay-compiler does not emit type definitions for in-fragment items, whether I'm using it with TypeScript or Flow!.

In particular, response.queryCities.location contains __fragments object which seems to be totally useless at the point of usage; it does not agree with the dev-time typings (" $fragmentRefs", " $data"). And obviously the TypeScript compiler cannot infer that location would have lat inside it.

So the question is:

  1. Am I misusing the fragments? I mean, I'm not reusing these fragments in any child components - rather, I simply use them to reduce repeating what I query, as above.
  2. Is there a way to make the compiler flatten the fragments, i.e. remove all fragmentRefs and instead actually return the hierarchical structure of the stuff I'm asking for?
  3. Why are the query results structs typed as they are? (" $data" does not exist in runtime etc)
wontfix

Most helpful comment

If the component defining the query needs to access queryCities.location.lat, the simplest and most robust solution is to fetch that field directly. So if the component that defines AvailableLocationsQuery needs the field, fetch it there.

All 5 comments

This is the data masking part, you can only access data that your component asked for, if you want to access data in other components check @inline

But you would break data composition

@sibelius Thank you - although I ended up doing @relay(mask:false) instead.

Inlining does not seem to work recursively. I actually have a situation where sub-fragments are reused, and both the fragment and sub-fragment are declared @inline - however, the sub-fragment does not seem to be inlined inside the resultant struct.

What do you mean by breaking the data composition in the @inline case?

Your component should only use what it asked for, if you consume other data it will be easier to break your application in the future

If the component defining the query needs to access queryCities.location.lat, the simplest and most robust solution is to fetch that field directly. So if the component that defines AvailableLocationsQuery needs the field, fetch it there.

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.

Was this page helpful?
0 / 5 - 0 ratings