All data flows downward from queries, which are what fetch data from/push data to the server. Generally speaking, queries are only executed by QueryRenderer
, although there are exceptions (e.g., pagination container queries). _Fragments are NEVER the original source of data from a server. If you see fragment ...
, it MUST receive its data from elsewhere, most likely a QueryRenderer
.
Take the following example:
const ProfileView = ({ profile }) => <span>My name: {profile.name}</span>;
const Profile = createFragmentContainer(ProfileView, {
profile: graphql`
fragment ProfileView_viewer on User {
name
}
`
});
<QueryRenderer
environment={environment}
query={graphql`
query ProfileQuery {
viewer {
...Profile_viewer
}
}
`}
render={({ props }) => {
if (props) return <Profile profile={???} />;
}}
/>
QueryRenderer
will request data from the GraphQL by submitting a query with a particular shape. That shape is partly created by the Profile_viewer
fragment, which is defined in the Profile
fragment container (not listed here).
However, this fragment-to-query dependency doesn't cause the data fetched by QueryRenderer
to magically appear inside of Profile
! The documentation misleadingly states that "the Component resulting from createFragmentContainer will receive" whatever props are defined on the fragmentSpec
. What it actually means is that fragment containers must receive data from the QueryRenderer
through the props defined on the fragmentSpec
. Once the fragment container receives the data, it will normalize it and make an object whose shape resembles the shape of the fragment.
Knowing that you must pass data from a QueryRenderer
to a fragment container through specific props is only half the battle. The other question is which specific data to pass.
In the above example, you may be tempted to replace profile={???}
with profile={props.viewer.profile}
, which would be incorrect. QueryRenderer
doesn't know anything about the internal data structure of your fragments, so there's no way that it would know about the profile
property in props.viewer.profile
. Instead, it only knows about the parent field, viewer
, which is specified within the query rather than the fragment. The correct line would be profile={props.viewer}
. Similarly, because Profile
knows nothing about QueryRenderer
's internal data structure, to access the viewer's name, you would read props.profile.name
inside ProfileView
rather than props.viewer.name
.