Last active
August 15, 2016 02:56
-
-
Save jbaxleyiii/54eda36c6b25e70eb8abbfa7375102c1 to your computer and use it in GitHub Desktop.
Apollo Fragment Composition
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component } from 'react'; | |
import { graphql } from 'react-apollo'; | |
import gql from 'graphql-tag'; | |
/* | |
GraphQL Enhancers (resuable and shareable) | |
Fragment Enhancers do the following: | |
- attach the fragment / fragments statically to the component (or a way for an operation enhancer to read) | |
- attach the variables statically to the component (or a way for an operation enhancer to read) | |
- allow refetching of the direct parent query they are used in based on variable change (or a manual refetch) | |
- pull the data out of the store for rendering (i.e not driven via props) | |
- can customize the children props to be passed | |
- are driven by the fragment name so they are still just plain GraphQL in both defintion and usage in operations. | |
- merge variables into parent queries? (dynamically create query variables would be awesome, is it a good idea?) | |
*/ | |
// this can be used by multiple parent queries (resuable) | |
const withPersonData = graphql(gql`fragment Avatar on Person { name, picUrl(size: $size) }`, { | |
options: (ownProps) => ({ variables: { size: ownProps.size || 200 }}), | |
props: ({ data }) => ({ photo: data.picUrl, name: data.name }), | |
}); | |
// this can be used by multiple parent queries (resuable) | |
const withAddress = graphql(gql`fragment Address on Person { city, zip, street1 }`); | |
// this can use multiple fragment enhancers | |
const withPeople = graphql(gql`query(cursor: ID!, size: Int!) { people(cursor: $cursor) { id, ...Avatar, ...Address } }`, { | |
options: (ownProps) => ({ variables: { cursor: ownProps.cursor }}), | |
fragmentEnhancers: [withPersonData, withAddress] | |
}) | |
/* | |
Components | |
*/ | |
const Person = ({ person }) => ( | |
<li> | |
<h1>{person.name}</h1> | |
<img src={person.picUrl} /> | |
</li> | |
); | |
Person.PropTypes = { | |
person: PropTypes.shape({ | |
name: PropTypes.string, | |
picUrl: PropTypes.string, | |
}), | |
refetch: PropTypes.func | |
} | |
const PersonWithData = withPersonData(Person); | |
const People = ({ data }) => ( | |
<ul> | |
{data.people && data.people.map(person => ( | |
<PersonWithData key={person.id} /> // notice no prop of person passed through | |
))} | |
</ul> | |
); | |
const PeopleWithData = withPeople(People); | |
People.PropTypes = { | |
data: PropTypes.shape({ | |
loading: PropTypes.boolean, | |
people: PropTypes.array, | |
error: PropTypes.object, | |
refetch: PropTypes.func, | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment