Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Efficient Data Fetching with GraphQL and Relay

Efficient Data Fetching with GraphQL and Relay

Dan Schafer

July 22, 2015
Tweet

More Decks by Dan Schafer

Other Decks in Programming

Transcript

  1. { id: 3500401, name: "Jing Chen", isViewerFriend: true, mutualFriends: {

    count: 195 }, profilePicture: { uri: "http://…", width: 50, height: 50 } }
  2. { id: 3500401, name: "Jing Chen", isViewerFriend: true, mutualFriends: {

    count: 195 }, profilePicture: { uri: "http://…", width: 50, height: 50 } }
  3. GraphQL { "node": { "id": "1572451031", "name": "Daniel Schafer" }

    } { node(id: 1572451031) { id name birthdate { month day } } }
  4. GraphQL { "node": { "id": "1572451031", "name": "Daniel Schafer", "birthdate":

    { "month": 1, "day": 17, } } } { node(id: 1572451031) { id name birthdate { month day } } }
  5. var FriendInfo = React.createClass({ render: function() { return ( <div>

    <span>{this.props.user.name}</span> <span>{this.props.user.mutualFriends.count} mutual friends</span> </div> ); } }); GraphQL + React
  6. var FriendInfo = React.createClass({ statics: { queries: { } }

    render: function() { return ( <div> <span>{this.props.user.name}</span> <span>{this.props.user.mutualFriends.count} mutual friends</span> </div> ); } }); GraphQL + React
  7. var FriendInfo = React.createClass({ statics: { queries: { user: function()

    { return graphql` User { name mutualFriends { count } } `; } } }, render: function() { return ( <div> <span>{this.props.user.name}</span> <span>{this.props.user.mutualFriends.count} mutual friends</span> </div> ); } }); GraphQL + React
  8. var FriendInfo = React.createClass({ statics: { queries: { user: function()

    { return graphql` User { name mutualFriends { count } } `; } } }, render: function() { return ( <div> <span>{this.props.user.name}</span> <span>{this.props.user.mutualFriends.count} mutual friends</span> </div> ); } }); GraphQL + React
  9. var FriendInfo = React.createClass({ statics: { queries: { user: function()

    { return graphql` User { name mutualFriends { count } } `; } } }, render: function() { return ( <div> <span>{this.props.user.name}</span> <span>{this.props.user.mutualFriends.count} mutual friends</span> </div> ); } }); GraphQL + React
  10. var FriendInfo = React.createClass({ statics: { queries: { user: function()

    { return graphql` User { name mutualFriends { count } } `; } } }, render: function() { return ( <div> <span>{this.props.user.name}</span> <span>{this.props.user.mutualFriends.count} mutual friends</span> </div> ); } }); GraphQL + React
  11. var FriendInfo = React.createClass({ statics: { queries: { user: function()

    { return graphql` User { name mutualFriends { count } } `; } } }, render: function() { return ( <div> <span>{this.props.user.name}</span> <span>{this.props.user.mutualFriends.count} mutual friends</span> </div> ); } }); GraphQL + React
  12. Composition var FriendListItem = React.createClass({ render: function() { return (

    <div> <ProfilePic user={this.props.user} /> <FriendInfo user={this.props.user} /> </div> ); } });
  13. Composition var FriendListItem = React.createClass({ statics: { queries: { user:

    function() { return graphql` User { ?? ?? } `; } } }, render: function() { return ( <div> <ProfilePic user={this.props.user} /> <FriendInfo user={this.props.user} /> </div> ); } });
  14. Composition var FriendListItem = React.createClass({ statics: { queries: { user:

    function() { return graphql` User { ${ProfilePic.getQuery(‘user’)}, ${FriendInfo.getQuery(‘user’)} } `; } } }, render: function() { return ( <div> <ProfilePic user={this.props.user} /> <FriendInfo user={this.props.user} /> </div> ); } });
  15. Lifecycle var FriendListItem = React.createClass({ statics: { queries: { user:

    function() { return graphql` User { ${ProfilePic.getQuery('user')} ${FriendInfo.getQuery('user')} } `; } } } }); Static View
  16. Lifecycle var FriendListItem = React.createClass({ statics: { queries: { user:

    function() { return graphql` User { ${ProfilePic.getQuery('user')} ${FriendInfo.getQuery('user')} } `; } } } }); Static View FriendListItem
  17. Lifecycle { node(id: 1572451031) { name mutualFriends { count },

    profilePicture { uri width height } } } Query Server ew
  18. Lifecycle { "node": { name: "Daniel Schafer", mutualFriends: { count:

    195 }, profilePicture: { uri: "http://...", width: 50, height: 50 } } } y Server Data
  19. var FriendInfo = React.createClass({ statics: { queries: { user: function()

    { return graphql` User { name mutualFriends { count } } `; } } }, render: function() { return ( <div> <span>{this.props.user.name}</span> <span>{this.props.user.mutualFriends.count} mutual friends</span> </div> ); } }); Response Shape
  20. Pagination { "1572451031": { "name": "Daniel Schafer" } } {

    node(id: 1572451031) { name friends { name } } }
  21. Pagination { "1572451031": { "name": "Daniel Schafer", "friends": [ {

    "name": "Jing Chen" }, { "name": "Lee Byron" }, { "name": "Nick Schrock" }, { "name": "Joe Savona" } ] } } { node(id: 1572451031) { name friends { name } } }
  22. Pagination { "1572451031": { "name": "Daniel Schafer", "friends": [ {

    "name": "Jing Chen" }, { "name": "Lee Byron" }, { "name": "Nick Schrock" }, { "name": "Joe Savona" } ] } } { node(id: 1572451031) { name friends(first: 2) { name } } }
  23. Pagination { "1572451031": { "name": "Daniel Schafer", "friends": [ {

    "name": "Jing Chen" }, { "name": "Lee Byron" } ] } } { node(id: 1572451031) { name friends(first: 2) { name } } }
  24. Pagination { "1572451031": { "name": "Daniel Schafer", "friends": [ {

    "name": "Jing Chen" }, { "name": "Lee Byron" } ] } } { node(id: 1572451031) { name friends(first: 2 offset: 2) { name } } }
  25. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": [ {

    "name": "Jing Chen" }, { "name": "Lee Byron" } ] } } { node(id: 1572451031) { name friends(first: 2) { name } } }
  26. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": [ {

    "name": "Jing Chen" }, { "name": "Lee Byron" } ] } } { node(id: 1572451031) { name friends(first: 2) { edges { node { name } cursor } } } }
  27. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": { "edges":

    [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ] } } } { node(id: 1572451031) { name friends(first: 2) { edges { node { name } cursor } } } }
  28. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": { "edges":

    [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ] } } } { node(id: 1572451031) { name friends(first: 2 after: 4802170) { edges { node { name } cursor } } } }
  29. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": { "edges":

    [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ] } } } { node(id: 1572451031) { name friends(first: 2 after: 4802170) { edges { node { name } cursor } } } } { "1572451031": { "name": "Daniel Schafer", "friends": { "edges": [ { "node": { "name": "Nick Schrock" }, "cursor": "37000641" }, { "node": { "name": "Joe Savona" }, "cursor": "842472" } ] } } }
  30. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": { "edges":

    [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ] } } } { node(id: 1572451031) { name friends(first: 2 after: 842472) { edges { node { name } cursor } } } } { "1572451031": { "name": "Daniel Schafer", "friends": { "edges": [ { "node": { "name": "Nick Schrock" }, "cursor": "37000641" }, { "node": { "name": "Joe Savona" }, "cursor": "842472" } ] } } }
  31. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": { "edges":

    [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ] } } } { node(id: 1572451031) { name friends(first: 2 after: 842472) { edges { node { name } cursor } } } } { "1572451031": { "name": "Daniel Schafer", "friends": { "edges": [] } } }
  32. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": { "edges":

    [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ] } } } { node(id: 1572451031) { name friends(first: 2) { edges { node { name } cursor } } } }
  33. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": { "edges":

    [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ] } } } { node(id: 1572451031) { name friends(first: 2) { edges { node { name } cursor } pageInfo { hasNextPage } } } } { "1572451031": { "name": "Daniel Schafer", "friends": { "edges": [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ] } } }
  34. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": { "edges":

    [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ] } } } { node(id: 1572451031) { name friends(first: 2) { edges { node { name } cursor } pageInfo { hasNextPage } } } } { "1572451031": { "name": "Daniel Schafer", "friends": { "edges": [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ], "pageInfo": { "hasNextPage": true }, } }
  35. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": { "edges":

    [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ] } } } { node(id: 1572451031) { name friends(first: 2 after: 4802170) { edges { node { name } cursor } pageInfo { hasNextPage } } } } { "1572451031": { "name": "Daniel Schafer", "friends": { "edges": [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ], "pageInfo": { "hasNextPage": true }, } }
  36. Cursors { "1572451031": { "name": "Daniel Schafer", "friends": { "edges":

    [ { "node": { "name": "Jing Chen" }, "cursor": "3500401" }, { "node": { "name": "Lee Byron" }, "cursor": "4802170" } ] } } } { node(id: 1572451031) { name friends(first: 2 after: 4802170) { edges { node { name } cursor } pageInfo { hasNextPage } } } } { "1572451031": { "name": "Daniel Schafer", "friends": { "edges": [ { "node": { "name": "Nick Schrock" }, "cursor": "37000641" }, { "node": { "name": "Joe Savona" }, "cursor": "842472" } ], "pageInfo": { "hasNextPage": false }, } }
  37. Connections in Relay var FriendList = React.createClass({ render: function() {

    return ( <div> { this.props.viewer.friends.map( function(user) { return <FriendListItem user={user} />; } ) } </div> ); } });
  38. Connections in Relay var FriendList = React.createClass({ statics: { queries:

    { viewer: function() { return graphql` Viewer { friends { ${FriendListItem.getQuery(‘user’)}, } } `; } } }, render: function() { ... } });
  39. Connections in Relay var FriendList = React.createClass({ statics: { queries:

    { viewer: function() { return graphql` Viewer { friends(first: 10) { ${FriendListItem.getQuery(‘user’)}, } } `; } } }, render: function() { ... } });
  40. Connections in Relay var FriendList = React.createClass({ statics: { queries:

    { viewer: function() { return graphql` Viewer { friends(first: 10) { ${FriendListItem.getQuery(‘user’)}, } } `; } } }, render: function() { ... } });
  41. Connections in Relay var FriendList = React.createClass({ statics: { queryParams:

    {count: 10}, queries: { viewer: function(params) { return graphql` Viewer { friends(first: ${params.count}) { ${FriendListItem.getQuery(‘user’)}, } } `; } } }, render: function() { ... } });
  42. Connections in Relay var FriendList = React.createClass({ statics: { queryParams:

    {count: 10}, queries: { viewer: function(params) { return graphql` Viewer { friends(first: ${params.count}) { ${FriendListItem.getQuery(‘user’)}, } } `; } } }, onScrollLoad: function() { this.setQueryParams({count: this.queryParams.count + 5}); }, render: function() { ... } });