Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GraphQL and Relay
Search
Helielson
January 29, 2016
Programming
2
180
GraphQL and Relay
Concepts, Spec and how we are using it at jusbrasil.com.br
Helielson
January 29, 2016
Tweet
Share
More Decks by Helielson
See All by Helielson
Relay @ Jusbrasil
helielson
0
170
Component-based development with React
helielson
1
150
React - A JavaScript library for building user interfaces
helielson
9
1.9k
Other Decks in Programming
See All in Programming
AIと一緒にレガシーに向き合ってみた
nyafunta9858
0
230
Unicodeどうしてる? PHPから見たUnicode対応と他言語での対応についてのお伺い
youkidearitai
PRO
1
2.5k
Oxlint JS plugins
kazupon
1
940
MDN Web Docs に日本語翻訳でコントリビュート
ohmori_yusuke
0
650
Amazon Bedrockを活用したRAGの品質管理パイプライン構築
tosuri13
4
650
AIによる開発の民主化を支える コンテキスト管理のこれまでとこれから
mulyu
3
270
Rust 製のコードエディタ “Zed” を使ってみた
nearme_tech
PRO
0
170
OSSとなったswift-buildで Xcodeのビルドを差し替えられるため 自分でXcodeを直せる時代になっている ダイアモンド問題編
yimajo
3
620
FOSDEM 2026: STUNMESH-go: Building P2P WireGuard Mesh Without Self-Hosted Infrastructure
tjjh89017
0
170
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
560
AIによるイベントストーミング図からのコード生成 / AI-powered code generation from Event Storming diagrams
nrslib
2
1.9k
CSC307 Lecture 01
javiergs
PRO
0
690
Featured
See All Featured
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
310
Being A Developer After 40
akosma
91
590k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
RailsConf 2023
tenderlove
30
1.3k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
3.9k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.1k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.6k
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
1
99
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Thoughts on Productivity
jonyablonski
74
5k
Why Our Code Smells
bkeepers
PRO
340
58k
Transcript
GraphQL and Relay
@helielson @hyetho @rodrigopr @rodrigoropr
Topics - GraphQL What is it? Motivation Spec Implementations How
we use it What is coming
Definition GraphQL is a query language designed to build client
applications by providing an intuitive and flexible syntax for describing their data requirements and interactions.
Why invent something new? What about REST and Ad hoc
endpoints?
REST problems - Multiple round trips to render single views
- Receives unnecessary data - Payloads tend to grow over time for all clients
- Code duplication - API changes with client need -
Hard to scale with multiple clients - Hard to keep backwards compatibility Ad hoc endpoints (view oriented)
How we think about data? - Not tables, joins or
URIs - But: - Objects - Properties - Relationships - What, not How
GraphQL
- Product-centric - Hierarchical - Client-specified queries - Strongly-typed Principles:
Product-centric
Hierarchical
{ post(id: 65) { title, votes, author { name, avatar
} } } Hierarchical
{ post(id: 65) { title, votes, author { name, avatar
} } } Hierarchical { "post": { "title": "Post title", "votes": 100, "author" { "name": "Didi", "avatar": "http://x.jpg" } } }
Strong-Typing
Client-specific Queries
Not tied to: - Language - Framework - Database -
Protocol
Schema - Think as a Graph - Define structure of
nodes (properties) - How they are connected
Schema User { name: String! email: String! followers: [User] isFriendOf(otherEmail:
String!): Boolean }
Schema query { post(postId: Int!): Post! user(email: String!): User! me:
User }
Type System - Interface - Object - Enum - Union
- List - Scalars: - String, Int, Boolean
Query language { user(email: "
[email protected]
") { name followers { name
} } }
query { user(email: "
[email protected]
") { ...userInfo followers { ...userInfo }
} } fragment userInfo on User { name, email lastPosts { ...somePostFrament } }
fragment petInfo on Pet { petName, owner { name }
… on Dog { noiseVolume: barkVolume } … on Cat { noiseVolume: meowVolume } }
Variables query houseTrainedQuery($atOtherHomes: Boolean) { dog { isHousetrained(atOtherHomes: $atOtherHomes) }
}
Fragment directives fragment maybeFragment on Query @include(if: $condition) { me
{ name } }
Fragment directives query myQuery($someTest: Boolean) { experimentalField @skip(if: $someTest) }
Mutation mutation { submitComment(postId: 1, user: "...", content: "") {
createdComment { id, url } } }
Open to optimizations - Batch - Cache - "DataLoader is
the true" http://github.com/facebook/dataloader
Network-GraphQL (how we are using) - Unify object definition -
Unify loader definition - Helper for thrift-style relationships - Add an extra optimization layer - Auto extract selections from query
Network-GraphQL (how we are using) - Define the schema based
on jusbrasil-types - Rethinking data structure - english - relationships - building as we need - Based on network Thrift API
What's coming next? - Open source movement - Improve data
coverage - Provide authorization in schema (acl) - Mutation (done) - Object authorization - Field authorization
Questions?
Relay
Topics - Relay What is it? Motivation Spec Implementation How
we use it What is coming
Definition A javascript framework for building data-driven react applications
Dispatcher View Store Action
Dispatcher View Store Action Server
Let's make an App !! Will be easy !!!!
None
How to load data from server?
<TopicTag /> <Feed /> <Document />
A lot of trips between server and client /feed #
get feed (documents ids) /documents/{id} # get a document /topics/{id} # get a topic Reuse the endpoint
A big payload /feed_with_topics_max_tree_documents One custom endpoint that loads everything
/feed?topics=true&max_documents=3 Multiple custom endpoints
And what about: Pagination? Ordering? Error handling? Retry? Caching?
Don't forget about writes: Conflicts? Write Coordination? Latency Compensation? State
Sync?
Nah... We can solve this! Let's combine X + Y
+ Z and solve it!
None
Want to introduce changes ??? First learn about the entire
project … :(
- How to fetch data - How to coordinate requests
- How to coordinate writes - How to handle retries/errors - How to keep server/app in sync - How to update view with changes - How to cache data - How to keep that all in your head - How to …. - Your App What you had to think about:
- What data to fetch - Your App What you
want to think:
Focus on what matters most! Relay make easy for developers
to focus on the product and forget about data access nuances
Declarative Colocation Mutations Principles
Declarative The component describe what it want
// Story.js export default class Story extends React.Component { render()
{ var story = this.props.story; return ( <View> <Image uri={story.author.profilePicture.uri} /> <Text>{story.author.name}</Text> <Text>{story.text}</Text> </View> ); } }
fragment on Story { text, author { name, profilePicture {
uri } } }
export class Story extends Component { … } export default
Relay.createContainer(Story, { fragments: { story: () => Relay.QL` fragment on Story { author { name profilePicture { uri } } text } `, }, });
export class Story extends React.Component { ... } export default
Relay.createContainer(Story, { fragments: { story: () => Relay.QL` fragment on Story { author { ... } } `, }, }); Colocation
Easy to compose
export class NewsFeed extends Component { … } export default
Relay.createContainer(NewsFeed, { fragments: { feed: () => Relay.QL` fragment on Feed { stories(first: $count) { // fetch viewer's stories edges { // traverse the graph node { ${Story.getFragment('story')} // compose child fragment } } } } `, }, });
class FeedRoute extends Relay.Route { static routeName = "FeedRoute"; static
queries = { feed: () => Relay.QL` query { userFeed(uid: $userID) } `, }; } var feedRoute = new FeedRoute({userID: '123'}); Query Routes
ReactDOM.render( <Relay.RootContainer Component={Feed} route={feedRouter} renderLoading={...} // optional renderFailure={...} // optional
renderFetched={...} // optional />, domElement ); Root Containers
A common problem: Pagination
export default Relay.createContainer(NewsFeed, { initialVariables: { count: 3 }, fragments:
{ feed: () => Relay.QL` fragment on Feed { stories(first: $count) { ... } } `, }, });
class NewsFeed extends React.Component { render() { ... } loadMore()
{ var count = this.props.relay.variables.count; this.props.relay.setVariables({ count: count + 5, }); } }
followers(first: Int, last: String) { edges { node // the
actual follower object, cursor // node identifier in the edge }, pageInfo { hasNextPage, lastCursor } } Pagination: How it works?
export default Relay.createContainer(Story, { fragments: { story: () => Relay.QL`
fragment on Story { author { name followers(first: $limit) @include(if: $isDesktop) { ... } } text } `, }, }); Directives
Mutations
getMutation() { ... } getFatQuery() { ... } getConfigs() {
... } getVariables() { ... } Defining a mutation
export default class LikePostMutation extends Relay.Mutation { getMutation() { ...
} getVariables() { ... } getConfigs() { ... } getFatQuery() { ... } } Defining the mutation
getMutation() { return Relay.QL`mutation{ likePost // `likePost` mutation must be
defined on the server }`; } getMutation()
getVariables() { return { id: this.props.post.postId, like: this.props.like }; }
getVariables()
getConfigs() { return [{ type: 'FIELDS_CHANGE', fieldIDs: { post: this.props.post.id
} }]; } getConfigs()
getFatQuery() { return Relay.QL` fragment on LikePostPayload { post {
id, likesCounter }, } `; } getFatQuery()
export class Story extends React.Component { handleEditPost() { const onFailure
= () => {}; const onSuccess = () => {}; Relay.Store.commitUpdate(new LikePostMutation({ post: this.props.post, like: true }), {onFailure, onSuccess}); } } Sending the mutation
getOptimisticResponse() { return { post: { id: this.props.post.id, likesCounter: this.props.post.likesCounter
+ 1 } } } getOptimisticResponse()
interface Node { id: ID! } type Post extends Node
{ id: ID!, … // post fields } Object Tracking:
- Server-side rendering support - React Router integration - Babel
Plugin - Active development: - Subscription (live) on the work - Client state is being discussed Important Details
- Work well with others tools - Flux, Redux, etc
- Patterns are still emerging Not a silver bullet
Question?