Relay Modern
Declarative Data Fetching
Sibelius Seraphini
Sibelius Seraphini
@sibelius @sseraphini
2
Data Fetching
Which problem does it solve?
3
- Duplicate fetch logic
- Caching is hard
- Data fetching is hard to optimize
- Hard to handle different endpoints
- Pagination can be tricky
- Underfetching
- Overfetching
Data Fetching is tricky
4
5
6
7
8
- Declarative (declare data your
component needs)
- Colocating (component + data
requirement)
- Performance
- Common patterns (e.g., pagination)
Value proposition
9
- Subscriptions
- Mutations
- Data consistency
- Optimistic updates
- Error handling
Value Proposition
10
- Static queries
- Ahead of time code generation
- Compat mode
- Simpler and more predictable API
- More light-weight (20% less)
- Faster performance
- Persisted Queries
- Garbage Collection
What's new in Relay Modern
11
- GraphQL Subscriptions & Live
Queries
- Injectable Custom Field Handlers
- Simpler Mutation API
- Client Schema Extensions
- Flowtype Generation
- Extensible Core
- Closer API to GraphQL Spec
- no need for Viewer (Relay Classic)
What's new in Relay Modern
12
Relay Modern
Concepts
13
const UserRow = ({ user }) => (
<View>
<Text>{user.name}</Text>
<Text>{user.email}</Text>
</View>
);
const UserRowFragmentContainer = createFragmentContainer(UserRow, {
user: graphql`
fragment UserRow_user on User {
name
email
}
`,
});
Data Components (aka containers)
14
<QueryRenderer
environment={environment}
query={graphql`
query UserQuery($id: ID!) {
user(id: $id) {
...UserRow_user
}
}
`}
variables={{id: '110798995619330'}}
render={({error, props}) => {
if (error) {
return <View>{error.message}</View>;
}
if (props) {
return <UserFragmentContainer {...props} />
}
return <View>Loading</View>;
}}
/>
QueryRenderer (root of Relay tree)
15
RefetchContainer
export default createRefetchContainer(FeedStories, {
feed: graphql`
fragment FeedStories_feed on Feed
@argumentDefinitions(
count: {type: "Int", defaultValue: 10}
) {
stories(first: $count) {
edges {
node {
id
...Story_story
}
}
}
}
`
},
graphql`
query FeedStoriesRefetchQuery($count: Int) {
feed {
...FeedStories_feed @arguments(count: $count)
}
}
`,
); 16
RefetchContainer - refetch
_loadMore() {
// Increments the number of stories being rendered by 10.
const refetchVariables = fragmentVariables => ({
count: fragmentVariables.count + 10,
});
this.props.relay.refetch(refetchVariables, null);
}
17
Mutations
- A Write then Read
const mutation = graphql`
mutation AddShipMutation($input: AddShipData!) {
addShip(input: $input) {
faction {
ships {
id
}
}
newShipEdge
}
}
`;
18
Mutations - Update Store
const configs = [{
type: 'RANGE_ADD',
parentID: 'shipId',
connectionInfo: [{
key: 'AddShip_ships',
rangeBehavior: 'append',
}],
edgeName: 'newShipEdge',
}];
- RANGE_ADD - add node to edge
- RANGE_DELETE - remove node from edge
- NODE_DELETE - remove node from store
- updater - imperative API
19
Subscriptions
const subscription = graphql`
subscription MarkReadNotificationSubscription(
$storyID: ID!
) {
markReadNotification(storyID: $storyID) {
notification {
seenState
}
}
}
`;
20
Debugging
21
Resources
22
- https://github.com/sibelius/ReactNavigationRel
ayModern
- https://reactjs.org/blog/2015/02/20/introducing-
relay-and-graphql.html
- https://facebook.github.io/relay/
- https://code-cartoons.com/a-cartoon-intro-to-fa
cebook-s-relay-part-1-3ec1a127bca5
I didn't mention
23
- GraphQL/Relay compiler
- Babel plugin Relay
- Live Queries
- PaginationContainer
- Mutation Updater Imperative API
- Relay Directives
- Relay Network Layer
- Relay Environment
- Cache
Is Relay Modern the Future?
Sibelius

Sibelius Seraphini - Relay Modern

  • 1.
    Relay Modern Declarative DataFetching Sibelius Seraphini
  • 2.
  • 3.
  • 4.
    - Duplicate fetchlogic - Caching is hard - Data fetching is hard to optimize - Hard to handle different endpoints - Pagination can be tricky - Underfetching - Overfetching Data Fetching is tricky 4
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
    - Declarative (declaredata your component needs) - Colocating (component + data requirement) - Performance - Common patterns (e.g., pagination) Value proposition 9
  • 10.
    - Subscriptions - Mutations -Data consistency - Optimistic updates - Error handling Value Proposition 10
  • 11.
    - Static queries -Ahead of time code generation - Compat mode - Simpler and more predictable API - More light-weight (20% less) - Faster performance - Persisted Queries - Garbage Collection What's new in Relay Modern 11
  • 12.
    - GraphQL Subscriptions& Live Queries - Injectable Custom Field Handlers - Simpler Mutation API - Client Schema Extensions - Flowtype Generation - Extensible Core - Closer API to GraphQL Spec - no need for Viewer (Relay Classic) What's new in Relay Modern 12
  • 13.
  • 14.
    const UserRow =({ user }) => ( <View> <Text>{user.name}</Text> <Text>{user.email}</Text> </View> ); const UserRowFragmentContainer = createFragmentContainer(UserRow, { user: graphql` fragment UserRow_user on User { name email } `, }); Data Components (aka containers) 14
  • 15.
    <QueryRenderer environment={environment} query={graphql` query UserQuery($id: ID!){ user(id: $id) { ...UserRow_user } } `} variables={{id: '110798995619330'}} render={({error, props}) => { if (error) { return <View>{error.message}</View>; } if (props) { return <UserFragmentContainer {...props} /> } return <View>Loading</View>; }} /> QueryRenderer (root of Relay tree) 15
  • 16.
    RefetchContainer export default createRefetchContainer(FeedStories,{ feed: graphql` fragment FeedStories_feed on Feed @argumentDefinitions( count: {type: "Int", defaultValue: 10} ) { stories(first: $count) { edges { node { id ...Story_story } } } } ` }, graphql` query FeedStoriesRefetchQuery($count: Int) { feed { ...FeedStories_feed @arguments(count: $count) } } `, ); 16
  • 17.
    RefetchContainer - refetch _loadMore(){ // Increments the number of stories being rendered by 10. const refetchVariables = fragmentVariables => ({ count: fragmentVariables.count + 10, }); this.props.relay.refetch(refetchVariables, null); } 17
  • 18.
    Mutations - A Writethen Read const mutation = graphql` mutation AddShipMutation($input: AddShipData!) { addShip(input: $input) { faction { ships { id } } newShipEdge } } `; 18
  • 19.
    Mutations - UpdateStore const configs = [{ type: 'RANGE_ADD', parentID: 'shipId', connectionInfo: [{ key: 'AddShip_ships', rangeBehavior: 'append', }], edgeName: 'newShipEdge', }]; - RANGE_ADD - add node to edge - RANGE_DELETE - remove node from edge - NODE_DELETE - remove node from store - updater - imperative API 19
  • 20.
    Subscriptions const subscription =graphql` subscription MarkReadNotificationSubscription( $storyID: ID! ) { markReadNotification(storyID: $storyID) { notification { seenState } } } `; 20
  • 21.
  • 22.
    Resources 22 - https://github.com/sibelius/ReactNavigationRel ayModern - https://reactjs.org/blog/2015/02/20/introducing- relay-and-graphql.html -https://facebook.github.io/relay/ - https://code-cartoons.com/a-cartoon-intro-to-fa cebook-s-relay-part-1-3ec1a127bca5
  • 23.
    I didn't mention 23 -GraphQL/Relay compiler - Babel plugin Relay - Live Queries - PaginationContainer - Mutation Updater Imperative API - Relay Directives - Relay Network Layer - Relay Environment - Cache
  • 24.
    Is Relay Modernthe Future? Sibelius