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
160
Component-based development with React
helielson
1
140
React - A JavaScript library for building user interfaces
helielson
9
1.9k
Other Decks in Programming
See All in Programming
詳解!defer panic recover のしくみ / Understanding defer, panic, and recover
convto
0
230
Rancher と Terraform
fufuhu
2
200
AIを活用し、今後に備えるための技術知識 / Basic Knowledge to Utilize AI
kishida
20
5k
ProxyによるWindow間RPC機構の構築
syumai
3
1k
ECS初心者の仲間 – TUIツール「e1s」の紹介
keidarcy
0
150
パッケージ設計の黒魔術/Kyoto.go#63
lufia
3
430
Ruby Parser progress report 2025
yui_knk
1
300
複雑なドメインに挑む.pdf
yukisakai1225
5
980
機能追加とリーダー業務の類似性
rinchoku
2
1.1k
Putting The Genie in the Bottle - A Crash Course on running LLMs on Android
iurysza
0
110
さようなら Date。 ようこそTemporal! 3年間先行利用して得られた知見の共有
8beeeaaat
2
1.3k
速いWebフレームワークを作る
yusukebe
5
1.7k
Featured
See All Featured
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
6k
Visualization
eitanlees
148
16k
The Cult of Friendly URLs
andyhume
79
6.6k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
358
30k
The Invisible Side of Design
smashingmag
301
51k
jQuery: Nuts, Bolts and Bling
dougneiner
64
7.9k
Thoughts on Productivity
jonyablonski
70
4.8k
A designer walks into a library…
pauljervisheath
207
24k
The Power of CSS Pseudo Elements
geoffreycrofte
77
5.9k
[RailsConf 2023] Rails as a piece of cake
palkan
57
5.8k
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?