Skip to content

Instantly share code, notes, and snippets.

@ersinakinci
Created January 28, 2020 00:39
Show Gist options
  • Save ersinakinci/c83e0d90b307ae36e49d12b3f8727a70 to your computer and use it in GitHub Desktop.
Save ersinakinci/c83e0d90b307ae36e49d12b3f8727a70 to your computer and use it in GitHub Desktop.
Relay/GraphQL notes

Data flow

All data flows from queries

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.

Data is passed to fragment containers from queries through props

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment