Hi all,
It seems like fragments are tightly coupled with React at the moment and it does not seem possible to declare a fragment without a react component and then simply use it in a query.
Is Relay Modern trying to enforce fragment colocation with a React Component ?
I'm going to assume that what you are trying to do is to spread in a fragment you have defined in a graphql template tag somewhere, and are failing to get the actual unmasked data. Something along the lines of the following:
const friendFragment = graphql`
fragment AppFriendFragment on User {
id
name
}
`;
const query = graphql`
query AppQuery {
viewer {
id
name
friends {
...AppFriendFragment
}
}
}
`;
const App = () => (
<QueryRenderer
query={query}
environment={environment}
render={({ props, error }) => {
// Logging props would give us something like so
// {
// "viewer": {
// "id": "1234",
// "name": "myUsername",
// "friends": [
// {
// "__fragments": {
// "AppFriendFragment": {}
// },
// "__id": "client:1234:friends:0"
// }
// ]
// }
// }
}}
/>
);
We wanted the friends array to have proper data, but we are instead getting masked data. Most of the time we actually do want masked data, and only when we pass this masked data to an appropriate <FragmentContainer /> will that data get unmasked.
Luckily there is a special @relay(mask: false) directive that allows you to get data selected via a fragment in an unmasked form. What we would do in the above example is this:
const query = graphql`
query AppQuery {
viewer {
id
name
friends {
# This tells relay we don't want the data selected by this fragment to be masked
...AppFriendFragment @relay(mask: false)
}
}
}
`;
Logging out props as before would instead give us the data we were after:
{
"viewer": {
"id": "1234",
"name": "myUsername",
"friends": [
{
"id": "2345",
"name": "someOtherUsername"
}
]
}
}
So, if you wanted, you could define that friendFragment anywhere you like (doesn't have to be colocated with a React component) and share it between many different queries.
You can read more about directives here: https://facebook.github.io/relay/docs/relay-directives.html
Hope that helps.
When I am using @relay(mask: false) I always get a warning like that:
Warning: RelayModernSelector: Expected object to contain data for fragment `FeedList_feed`, got
{"edges":[{"node" [...] }]} Make sure that the parent operation/fragment included fragment
...FeedList_feed` without `@relay(mask: false).
Is this ignorable? How would I fix that?
Thanks a lot @nirrek , exactly what I was looking for.
@tlvenn can we close this?
Yes, thanks again @nirrek and I do believe there is something missing in the doc to highlight this better but I am not too sure where would that be.
Most helpful comment
I'm going to assume that what you are trying to do is to spread in a fragment you have defined in a
graphqltemplate tag somewhere, and are failing to get the actual unmasked data. Something along the lines of the following:We wanted the friends array to have proper data, but we are instead getting masked data. Most of the time we actually do want masked data, and only when we pass this masked data to an appropriate
<FragmentContainer />will that data get unmasked.Luckily there is a special
@relay(mask: false)directive that allows you to get data selected via a fragment in an unmasked form. What we would do in the above example is this:Logging out props as before would instead give us the data we were after:
So, if you wanted, you could define that
friendFragmentanywhere you like (doesn't have to be colocated with a React component) and share it between many different queries.You can read more about directives here: https://facebook.github.io/relay/docs/relay-directives.html
Hope that helps.