Skip to content

Instantly share code, notes, and snippets.

@jbaxleyiii
Last active August 15, 2016 02:56
Show Gist options
  • Save jbaxleyiii/54eda36c6b25e70eb8abbfa7375102c1 to your computer and use it in GitHub Desktop.
Save jbaxleyiii/54eda36c6b25e70eb8abbfa7375102c1 to your computer and use it in GitHub Desktop.
Apollo Fragment Composition
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