SlideShare a Scribd company logo
1 of 63
Download to read offline
Nikolas Burk šŸ‘‹
Developer at Graphcool
$ whoami
@nikolasburk
Launch Week šŸš€
Product Hunt > 1000 upvotesHacker News #1
Getting Started with
Relay Modern
1. Relay - A Brief History
2. Data Fetching
3. Mutations
4. More Features in Relay Modern
Agenda
@nikolasburk
Relay - A Brief History
@nikolasburk
Relay - A Brief History
@nikolasburk
01/2015
1st talk about Relay
@React.js Conf 2015
2012
FB starts using
GraphQL
02/2015
šŸ—£
Announcing Relay will
be open-source
08/2015
Relay is
open-source šŸŽ‰
08/2016
šŸ—£
Announcing plans
for ā€œRelay 2ā€
04/2017
Introducing
Relay Modern
GraphQL Clients
- homegrown by Facebook
- main goal: performance
- learning curve
- community-driven
- main goal: ļ¬‚exibility
- easy-to-get-started
@nikolasburk
Data Fetching
@nikolasburk
Traditional Data Fetching with REST
1. construct & send HTTP request
(e.g. with fetch)
2. receive & parse server response
3. store data locally
4. display data in UI
šŸ˜
@nikolasburk
Declarative Data Fetching with GraphQL
1. describe data dependencies
2. display data in UI
šŸ˜
@nikolasburk
Relayā€™s core idea is to couple a view
component with its data dependencies
@nikolasburk
Example:
Simple Instagram App
@nikolasburk
Post Post
ListPage
App
@nikolasburk
class Post extends React.Component {
render () {
return (
<div>
<img
src={this.props.post.imageUrl}
/>
<div>
{this.props.post.description}
</div>
</div>
)
}
}
export default createFragmentContainer(Post, graphql`
fragment Post_post on Post {
id
description
imageUrl
}
`)
Post.js
@nikolasburk
class Post extends React.Component {
render () {
return (
<div>
<img
src={this.props.post.imageUrl}
/>
<div>
{this.props.post.description}
</div>
</div>
)
}
}
export default createFragmentContainer(Post, graphql`
fragment Post_post on Post {
id
description
imageUrl
}
`)
Post.js
@nikolasburk
class Post extends React.Component {
render () {
return (
<div>
<img
src={this.props.post.imageUrl}
/>
<div>
{this.props.post.description}
</div>
</div>
)
}
}
export default createFragmentContainer(Post, graphql`
fragment Post_post on Post {
id
description
imageUrl
}
`)
Post.js
@nikolasburk
class Post extends React.Component {
render () {
return (
<div>
<img
src={this.props.post.imageUrl}
/>
<div>
{this.props.post.description}
</div>
</div>
)
}
}
export default createFragmentContainer(Post, graphql`
fragment Post_post on Post {
id
description
imageUrl
}
`)
Post.js
@nikolasburk
class Post extends React.Component {
render () {
return (
<div>
<img
src={this.props.post.imageUrl}
/>
<div>
{this.props.post.description}
</div>
</div>
)
}
}
export default createFragmentContainer(Post, graphql`
fragment Post_post on Post {
id
description
imageUrl
}
`)
Post.js
@nikolasburk
class Post extends React.Component {
render () {
return (
<div>
<img
src={this.props.post.imageUrl}
/>
<div>
{this.props.post.description}
</div>
</div>
)
}
}
export default createFragmentContainer(Post, graphql`
fragment Post_post on Post {
id
description
imageUrl
}
`)
Post.js
@nikolasburk
export default createFragmentContainer(ListPage, graphql`
fragment ListPage_viewer on Viewer {
allPosts @connection(key: ā€œListPage_allPosts") {
edges {
node {
ā€¦Post_post # from Post.js
}
}
}
}
`)
class ListPage extends React.Component {
render () {
return (
<div>
{this.props.viewer.allPosts.edges.map(({node}) =>
<Post key={node.id} post={node} />
)}
</div>
)
}
}
ListPage.js
@nikolasburk
export default createFragmentContainer(ListPage, graphql`
fragment ListPage_viewer on Viewer {
allPosts @connection(key: ā€œListPage_allPosts") {
edges {
node {
...Post_post
}
}
}
}
`)
class ListPage extends React.Component {
render () {
return (
<div>
{this.props.viewer.allPosts.edges.map(({node}) =>
<Post key={node.id} post={node} />
)}
</div>
)
}
}
ListPage.js
@nikolasburk
export default createFragmentContainer(ListPage, graphql`
fragment ListPage_viewer on Viewer {
allPosts @connection(key: ā€œListPage_allPosts") {
edges {
node {
...Post_post
}
}
}
}
`)
class ListPage extends React.Component {
render () {
return (
<div>
{this.props.viewer.allPosts.edges.map(({node}) =>
<Post key={node.id} post={node} />
)}
</div>
)
}
}
ListPage.js
@nikolasburk
export default createFragmentContainer(ListPage, graphql`
fragment ListPage_viewer on Viewer {
allPosts @connection(key: ā€œListPage_allPosts") {
edges {
node {
...Post_post
}
}
}
}
`)
class ListPage extends React.Component {
render () {
return (
<div>
{this.props.viewer.allPosts.edges.map(({node}) =>
<Post key={node.id} post={node} />
)}
</div>
)
}
}
ListPage.js
@nikolasburk
export default createFragmentContainer(ListPage, graphql`
fragment ListPage_viewer on Viewer {
allPosts @connection(key: ā€œListPage_allPosts") {
edges {
node {
...Post_post
}
}
}
}
`)
class ListPage extends React.Component {
render () {
return (
<div>
{this.props.viewer.allPosts.edges.map(({node}) =>
<Post key={node.id} post={node} />
)}
</div>
)
}
}
ListPage.js
@nikolasburk
export default createFragmentContainer(ListPage, graphql`
fragment ListPage_viewer on Viewer {
allPosts @connection(key: "ListPage_allPosts") {
edges {
node {
...Post_post
}
}
}
}
`)
class ListPage extends React.Component {
render () {
return (
<div>
{this.props.viewer.allPosts.edges.map(({node}) =>
<Post key={node.id} post={node} />
)}
</div>
)
}
}
ListPage.js
@nikolasburk
The QueryRenderer
QueryRenderer is the root of a Relay tree.
It takes a query, fetches the data
and calls the render callback.
@nikolasburk
class App extends Component {
render() {
return (
<QueryRenderer
environment={environment}
query={AppAllPostQuery}
render={({error, props}) => {
if (error) {
return <div>{error.message}</div>
} else if (props) {
return <ListPage viewer={props.viewer} />
}
return <div>Loading</div>
}}
/>
)
}
}
const AppAllPostQuery = graphql`
query AppAllPostQuery {
viewer {
ā€¦ListPage_viewer
}
}
`
App.js
@nikolasburk
class App extends Component {
render() {
return (
<QueryRenderer
environment={environment}
query={AppAllPostQuery}
render={({error, props}) => {
if (error) {
return <div>{error.message}</div>
} else if (props) {
return <ListPage viewer={props.viewer} />
}
return <div>Loading</div>
}}
/>
)
}
}
const AppAllPostQuery = graphql`
query AppAllPostQuery {
viewer {
ā€¦ListPage_viewer
}
}
`
App.js
@nikolasburk
class App extends Component {
render() {
return (
<QueryRenderer
environment={environment}
query={AppAllPostQuery}
render={({error, props}) => {
if (error) {
return <div>{error.message}</div>
} else if (props) {
return <ListPage viewer={props.viewer} />
}
return <div>Loading</div>
}}
/>
)
}
}
const AppAllPostQuery = graphql`
query AppAllPostQuery {
viewer {
ā€¦ListPage_viewer # from ListPage.js
}
}
`
App.js
@nikolasburk
class App extends Component {
render() {
return (
<QueryRenderer
environment={environment}
query={AppAllPostQuery}
render={({error, props}) => {
if (error) {
return <div>{error.message}</div>
} else if (props) {
return <ListPage viewer={props.viewer} />
}
return <div>Loading</div>
}}
/>
)
}
}
const AppAllPostQuery = graphql`
query AppAllPostQuery {
viewer {
ā€¦ListPage_viewer
}
}
`
ListPage.js
@nikolasburk
class App extends Component {
render() {
return (
<QueryRenderer
environment={environment}
query={AppAllPostQuery}
render={({error, props}) => {
if (error) {
return <div>{error.message}</div>
} else if (props) {
return <ListPage viewer={props.viewer} />
}
return <div>Loading</div>
}}
/>
)
}
}
const AppAllPostQuery = graphql`
query AppAllPostQuery {
viewer {
ā€¦ListPage_viewer
}
}
`
ListPage.js
@nikolasburk
class App extends Component {
render() {
return (
<QueryRenderer
environment={environment}
query={AppAllPostQuery}
render={({error, props}) => {
if (error) {
return <div>{error.message}</div>
} else if (props) {
return <ListPage viewer={props.viewer} />
}
return <div>Loading</div>
}}
/>
)
}
}
const AppAllPostQuery = graphql`
query AppAllPostQuery {
viewer {
ā€¦ListPage_viewer
}
}
`
ListPage.js
@nikolasburk
class App extends Component {
render() {
return (
<QueryRenderer
environment={environment}
query={AppAllPostQuery}
render={({error, props}) => {
if (error) {
return <div>{error.message}</div>
} else if (props) {
return <ListPage viewer={props.viewer} />
}
return <div>Loading</div>
}}
/>
)
}
}
const AppAllPostQuery = graphql`
query AppAllPostQuery {
viewer {
ā€¦ListPage_viewer
}
}
`
ListPage.js
@nikolasburk
Mutations
@nikolasburk
Mutations in Relay Modern
const {commitMutation} = require('react-relay')
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
@nikolasburk
Mutations in Relay Modern
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
@nikolasburk
Mutations in Relay Modern
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
@nikolasburk
Mutations in Relay Modern
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
const mutation = graphql`
mutation CreatePostMutation($input: CreatePostInput!) {
createPost(input: $input) {
post {
id
description
imageUrl
}
}
}
`
@nikolasburk
Mutations in Relay Modern
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
}
)
@nikolasburk
Mutations in Relay Modern
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
const variables = {
input: {
description: ā€œNice Sunsetā€,
imageUrl: ā€œwww.example.org/sunset.jpgā€,
}
}
@nikolasburk
Mutations in Relay Modern
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
}
)
@nikolasburk
Mutations in Relay Modern
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
}
)
@nikolasburk
Updating the Cache
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
updater: (proxyStore) => {
const createPostField = proxyStore.getRootField('createPost')
const newPost = createPostField.getLinkedRecord('post')
const viewerProxy = proxyStore.get(viewerId)
const connection =
ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts')
ConnectionHandler.insertEdgeAfter(connection, newPost)
}
const mutation = graphql`
mutation CreatePostMutation($input: CreatePostInput!) {
createPost(input: $input) {
post {
id
description
imageUrl
}
}
}
`
@nikolasburk
Updating the Cache
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
updater: (proxyStore) => {
const createPostField = proxyStore.getRootField('createPost')
const newPost = createPostField.getLinkedRecord('post')
const viewerProxy = proxyStore.get(viewerId)
const connection =
ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts')
ConnectionHandler.insertEdgeAfter(connection, newPost)
}
const mutation = graphql`
mutation CreatePostMutation($input: CreatePostInput!) {
createPost(input: $input) {
post {
id
description
imageUrl
}
}
}
`
@nikolasburk
Updating the Cache
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
updater: (proxyStore) => {
const createPostField = proxyStore.getRootField('createPost')
const newPost = createPostField.getLinkedRecord('post')
const viewerProxy = proxyStore.get(viewerId)
const connection =
ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts')
ConnectionHandler.insertEdgeAfter(connection, newPost)
}
const mutation = graphql`
mutation CreatePostMutation($input: CreatePostInput!) {
createPost(input: $input) {
post {
id
description
imageUrl
}
}
}
`
@nikolasburk
Updating the Cache
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
updater: (proxyStore) => {
const createPostField = proxyStore.getRootField('createPost')
const newPost = createPostField.getLinkedRecord('post')
const viewerProxy = proxyStore.get(viewerId)
const connection =
ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts')
ConnectionHandler.insertEdgeAfter(connection, newPost)
}
fragment ListPage_viewer on Viewer {
allPosts @connection(key: "ListPage_allPosts") {
edges {
node {
...Post_post
}
}
}
}
@nikolasburk
Updating the Cache
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
updater: (proxyStore) => {
const createPostField = proxyStore.getRootField('createPost')
const newPost = createPostField.getLinkedRecord('post')
const viewerProxy = proxyStore.get(viewerId)
const connection =
ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts')
ConnectionHandler.insertEdgeAfter(connection, newPost)
}
fragment ListPage_viewer on Viewer {
allPosts @connection(key: "ListPage_allPosts") {
edges {
node {
...Post_post
}
}
}
}
@nikolasburk
Mutations in Relay Modern
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
}
)
@nikolasburk
Updating the Cache (Optimistically)
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
optimisticUpdater: (proxyStore) => {
const id = 'client:newPost:' + tempID++
const newPost = proxyStore.create(id, 'Post')
newPost.setValue(description, 'description')
newPost.setValue(imageUrl, 'imageUrl')
const viewerProxy = proxyStore.get(viewerId)
const connection =
ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts')
ConnectionHandler.insertEdgeAfter(connection, newPost)
}
@nikolasburk
Updating the Cache (Optimistically)
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
optimisticUpdater: (proxyStore) => {
const id = 'client:newPost:' + tempID++
const newPost = proxyStore.create(id, 'Post')
newPost.setValue(description, 'description')
newPost.setValue(imageUrl, 'imageUrl')
const viewerProxy = proxyStore.get(viewerId)
const connection =
ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts')
ConnectionHandler.insertEdgeAfter(connection, newPost)
}
@nikolasburk
Updating the Cache (Optimistically)
commitMutation(
environment: Environment,
config: {
mutation: GraphQLTaggedNode,
variables: Variables,
onCompleted: (response) => void,
onError: (error) => void,
updater: (store) => void,
optimisticUpdater: (store) => void,
},
)
optimisticUpdater: (proxyStore) => {
const id = 'client:newPost:' + tempID++
const newPost = proxyStore.create(id, 'Post')
newPost.setValue(description, 'description')
newPost.setValue(imageUrl, 'imageUrl')
const viewerProxy = proxyStore.get(viewerId)
const connection =
ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts')
ConnectionHandler.insertEdgeAfter(connection, newPost)
}
@nikolasburk
More Features in Relay Modern
@nikolasburk
The Relay Environment šŸŒ
ā€¦.bundles together the conļ¬guration, cache storage, and
network-handling that Relay needs in order to operate.
const environment = new Environment({
network,
store,
})
@nikolasburk
GraphQL Subscriptions āš”
@nikolasburk
ā€¦.allow to receive realtime events from the server.
Client Schema Extensions šŸ’¼
@nikolasburk
ā€¦.allow to store client state.
extend type Post {
hasViewerSeen: Boolean
}
Garbage Collection šŸ—‘
@nikolasburk
ā€¦ removes objects from memory before the
JS Garbage Collector runs.
Compatibility Mode šŸŽÆ
@nikolasburk
ā€¦ allows to incrementally update an application
from Relay Classic to Relay Modern.
Resources šŸ“š
ā€¢ Quickstart (Sample Code)
https://github.com/graphcool-examples/react-graphql/tree/master/quickstart-with-relay-modern
ā€¢ 1st talk about Relay @ React.JS Conf 2015 (Video)
https://www.youtube.com/watch?v=9sc8Pyc51uU
ā€¢ Introducing Relay and GraphQL (Article)
https://facebook.github.io/react/blog/2015/02/20/introducing-relay-and-graphql.html
ā€¢ Building Relay Modern (Article)
https://wincent.com/blog/relay-modern
ā€¢ Getting Started with Relay Modern (Tutorial)
https://www.graph.cool/docs/tutorials/relay-modern-getting-started-woodito7ug/
@nikolasburk
Community šŸ™Œ
ā€¢ slack.graph.cool (> 2000 members)
ā€¢ GraphQL Weekly Newsletter
ā€¢ GraphQL Radio Podcast
@nikolasburk
Weā€™re hiring!
www.graph.cool/jobs
@nikolasburk
Thank you! šŸ™‡
ā€¦ any questions?
@nikolasburk

More Related Content

What's hot

Migrating Airflow-based Apache Spark Jobs to Kubernetes ā€“ the Native Way
Migrating Airflow-based Apache Spark Jobs to Kubernetes ā€“ the Native WayMigrating Airflow-based Apache Spark Jobs to Kubernetes ā€“ the Native Way
Migrating Airflow-based Apache Spark Jobs to Kubernetes ā€“ the Native WayDatabricks
Ā 
Solutions for bi-directional integration between Oracle RDBMS & Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS & Apache KafkaSolutions for bi-directional integration between Oracle RDBMS & Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS & Apache KafkaGuido Schmutz
Ā 
Event sourcing - what could possibly go wrong ? Devoxx PL 2021
Event sourcing  - what could possibly go wrong ? Devoxx PL 2021Event sourcing  - what could possibly go wrong ? Devoxx PL 2021
Event sourcing - what could possibly go wrong ? Devoxx PL 2021Andrzej Ludwikowski
Ā 
Data all over the place! How SQL and Apache Calcite bring sanity to streaming...
Data all over the place! How SQL and Apache Calcite bring sanity to streaming...Data all over the place! How SQL and Apache Calcite bring sanity to streaming...
Data all over the place! How SQL and Apache Calcite bring sanity to streaming...Julian Hyde
Ā 
Extending Apache Spark ā€“ Beyond Spark Session Extensions
Extending Apache Spark ā€“ Beyond Spark Session ExtensionsExtending Apache Spark ā€“ Beyond Spark Session Extensions
Extending Apache Spark ā€“ Beyond Spark Session ExtensionsDatabricks
Ā 
Flink Forward SF 2017: David Hardwick, Sean Hester & David Brelloch - Dynami...
Flink Forward SF 2017: David Hardwick, Sean Hester & David Brelloch -  Dynami...Flink Forward SF 2017: David Hardwick, Sean Hester & David Brelloch -  Dynami...
Flink Forward SF 2017: David Hardwick, Sean Hester & David Brelloch - Dynami...Flink Forward
Ā 
Deep dive into stateful stream processing in structured streaming by Tathaga...
Deep dive into stateful stream processing in structured streaming  by Tathaga...Deep dive into stateful stream processing in structured streaming  by Tathaga...
Deep dive into stateful stream processing in structured streaming by Tathaga...Databricks
Ā 
Interactive Kafka Streams
Interactive Kafka StreamsInteractive Kafka Streams
Interactive Kafka Streamsconfluent
Ā 
Samza 0.13 meetup slide v1.0.pptx
Samza 0.13 meetup slide   v1.0.pptxSamza 0.13 meetup slide   v1.0.pptx
Samza 0.13 meetup slide v1.0.pptxYi Pan
Ā 
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS and Apache KafkaSolutions for bi-directional integration between Oracle RDBMS and Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS and Apache KafkaGuido Schmutz
Ā 
A Deep Dive into Stateful Stream Processing in Structured Streaming with Tath...
A Deep Dive into Stateful Stream Processing in Structured Streaming with Tath...A Deep Dive into Stateful Stream Processing in Structured Streaming with Tath...
A Deep Dive into Stateful Stream Processing in Structured Streaming with Tath...Databricks
Ā 
Component level caching with react
Component level caching with reactComponent level caching with react
Component level caching with reactAnusheelSingh2
Ā 
Performance Analysis and Optimizations for Kafka Streams Applications
Performance Analysis and Optimizations for Kafka Streams ApplicationsPerformance Analysis and Optimizations for Kafka Streams Applications
Performance Analysis and Optimizations for Kafka Streams ApplicationsGuozhang Wang
Ā 
Distributed Real-Time Stream Processing: Why and How 2.0
Distributed Real-Time Stream Processing:  Why and How 2.0Distributed Real-Time Stream Processing:  Why and How 2.0
Distributed Real-Time Stream Processing: Why and How 2.0Petr Zapletal
Ā 
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and TypescriptMongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and TypescriptMongoDB
Ā 
Deep Dive into Stateful Stream Processing in Structured Streaming with Tathag...
Deep Dive into Stateful Stream Processing in Structured Streaming with Tathag...Deep Dive into Stateful Stream Processing in Structured Streaming with Tathag...
Deep Dive into Stateful Stream Processing in Structured Streaming with Tathag...Databricks
Ā 
User Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryUser Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryDatabricks
Ā 

What's hot (18)

Ajax
AjaxAjax
Ajax
Ā 
Migrating Airflow-based Apache Spark Jobs to Kubernetes ā€“ the Native Way
Migrating Airflow-based Apache Spark Jobs to Kubernetes ā€“ the Native WayMigrating Airflow-based Apache Spark Jobs to Kubernetes ā€“ the Native Way
Migrating Airflow-based Apache Spark Jobs to Kubernetes ā€“ the Native Way
Ā 
Solutions for bi-directional integration between Oracle RDBMS & Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS & Apache KafkaSolutions for bi-directional integration between Oracle RDBMS & Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS & Apache Kafka
Ā 
Event sourcing - what could possibly go wrong ? Devoxx PL 2021
Event sourcing  - what could possibly go wrong ? Devoxx PL 2021Event sourcing  - what could possibly go wrong ? Devoxx PL 2021
Event sourcing - what could possibly go wrong ? Devoxx PL 2021
Ā 
Data all over the place! How SQL and Apache Calcite bring sanity to streaming...
Data all over the place! How SQL and Apache Calcite bring sanity to streaming...Data all over the place! How SQL and Apache Calcite bring sanity to streaming...
Data all over the place! How SQL and Apache Calcite bring sanity to streaming...
Ā 
Extending Apache Spark ā€“ Beyond Spark Session Extensions
Extending Apache Spark ā€“ Beyond Spark Session ExtensionsExtending Apache Spark ā€“ Beyond Spark Session Extensions
Extending Apache Spark ā€“ Beyond Spark Session Extensions
Ā 
Flink Forward SF 2017: David Hardwick, Sean Hester & David Brelloch - Dynami...
Flink Forward SF 2017: David Hardwick, Sean Hester & David Brelloch -  Dynami...Flink Forward SF 2017: David Hardwick, Sean Hester & David Brelloch -  Dynami...
Flink Forward SF 2017: David Hardwick, Sean Hester & David Brelloch - Dynami...
Ā 
Deep dive into stateful stream processing in structured streaming by Tathaga...
Deep dive into stateful stream processing in structured streaming  by Tathaga...Deep dive into stateful stream processing in structured streaming  by Tathaga...
Deep dive into stateful stream processing in structured streaming by Tathaga...
Ā 
Interactive Kafka Streams
Interactive Kafka StreamsInteractive Kafka Streams
Interactive Kafka Streams
Ā 
Samza 0.13 meetup slide v1.0.pptx
Samza 0.13 meetup slide   v1.0.pptxSamza 0.13 meetup slide   v1.0.pptx
Samza 0.13 meetup slide v1.0.pptx
Ā 
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS and Apache KafkaSolutions for bi-directional integration between Oracle RDBMS and Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafka
Ā 
A Deep Dive into Stateful Stream Processing in Structured Streaming with Tath...
A Deep Dive into Stateful Stream Processing in Structured Streaming with Tath...A Deep Dive into Stateful Stream Processing in Structured Streaming with Tath...
A Deep Dive into Stateful Stream Processing in Structured Streaming with Tath...
Ā 
Component level caching with react
Component level caching with reactComponent level caching with react
Component level caching with react
Ā 
Performance Analysis and Optimizations for Kafka Streams Applications
Performance Analysis and Optimizations for Kafka Streams ApplicationsPerformance Analysis and Optimizations for Kafka Streams Applications
Performance Analysis and Optimizations for Kafka Streams Applications
Ā 
Distributed Real-Time Stream Processing: Why and How 2.0
Distributed Real-Time Stream Processing:  Why and How 2.0Distributed Real-Time Stream Processing:  Why and How 2.0
Distributed Real-Time Stream Processing: Why and How 2.0
Ā 
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and TypescriptMongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
Ā 
Deep Dive into Stateful Stream Processing in Structured Streaming with Tathag...
Deep Dive into Stateful Stream Processing in Structured Streaming with Tathag...Deep Dive into Stateful Stream Processing in Structured Streaming with Tathag...
Deep Dive into Stateful Stream Processing in Structured Streaming with Tathag...
Ā 
User Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love StoryUser Defined Aggregation in Apache Spark: A Love Story
User Defined Aggregation in Apache Spark: A Love Story
Ā 

Similar to Getting Started with Relay Modern

React 101
React 101React 101
React 101Casear Chu
Ā 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Elyse Kolker Gordon
Ā 
2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & WebpackCodifly
Ā 
Learning React: Facebook's Javascript Library For Building User Interfaces
Learning React: Facebook's Javascript Library For Building User InterfacesLearning React: Facebook's Javascript Library For Building User Interfaces
Learning React: Facebook's Javascript Library For Building User InterfacesKen Wheeler
Ā 
Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Robert DeLuca
Ā 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux IntroductionNikolaus Graf
Ā 
Flask and Angular: An approach to build robust platforms
Flask and Angular:  An approach to build robust platformsFlask and Angular:  An approach to build robust platforms
Flask and Angular: An approach to build robust platformsAyush Sharma
Ā 
SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!SĆ©bastien Levert
Ā 
Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...
Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...
Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...Luciano Mammino
Ā 
React on Rails - RailsConf 2017 (Phoenix)
 React on Rails - RailsConf 2017 (Phoenix) React on Rails - RailsConf 2017 (Phoenix)
React on Rails - RailsConf 2017 (Phoenix)Jo Cranford
Ā 
React.js: You deserve to know about it
React.js: You deserve to know about itReact.js: You deserve to know about it
React.js: You deserve to know about itAnderson Aguiar
Ā 
Dive into React Performance
Dive into React PerformanceDive into React Performance
Dive into React PerformanceChing Ting Wu
Ā 
How Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fastHow Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fastAtlassian
Ā 
React table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterReact table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterKaty Slemon
Ā 
Big Data processing with Spark, Scala or Java?
Big Data processing with Spark, Scala or Java?Big Data processing with Spark, Scala or Java?
Big Data processing with Spark, Scala or Java?Erik-Berndt Scheper
Ā 
Office 365 Groups and Tasks API - Getting Started
Office 365 Groups and Tasks API - Getting StartedOffice 365 Groups and Tasks API - Getting Started
Office 365 Groups and Tasks API - Getting StartedDragan Panjkov
Ā 
Time to React!
Time to React!Time to React!
Time to React!STX Next
Ā 

Similar to Getting Started with Relay Modern (20)

React js
React jsReact js
React js
Ā 
React 101
React 101React 101
React 101
Ā 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017
Ā 
2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack
Ā 
Learning React: Facebook's Javascript Library For Building User Interfaces
Learning React: Facebook's Javascript Library For Building User InterfacesLearning React: Facebook's Javascript Library For Building User Interfaces
Learning React: Facebook's Javascript Library For Building User Interfaces
Ā 
Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React
Ā 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux Introduction
Ā 
Flask and Angular: An approach to build robust platforms
Flask and Angular:  An approach to build robust platformsFlask and Angular:  An approach to build robust platforms
Flask and Angular: An approach to build robust platforms
Ā 
SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!
Ā 
React lecture
React lectureReact lecture
React lecture
Ā 
Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...
Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...
Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...
Ā 
React on Rails - RailsConf 2017 (Phoenix)
 React on Rails - RailsConf 2017 (Phoenix) React on Rails - RailsConf 2017 (Phoenix)
React on Rails - RailsConf 2017 (Phoenix)
Ā 
React.js: You deserve to know about it
React.js: You deserve to know about itReact.js: You deserve to know about it
React.js: You deserve to know about it
Ā 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
Ā 
Dive into React Performance
Dive into React PerformanceDive into React Performance
Dive into React Performance
Ā 
How Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fastHow Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fast
Ā 
React table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterReact table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilter
Ā 
Big Data processing with Spark, Scala or Java?
Big Data processing with Spark, Scala or Java?Big Data processing with Spark, Scala or Java?
Big Data processing with Spark, Scala or Java?
Ā 
Office 365 Groups and Tasks API - Getting Started
Office 365 Groups and Tasks API - Getting StartedOffice 365 Groups and Tasks API - Getting Started
Office 365 Groups and Tasks API - Getting Started
Ā 
Time to React!
Time to React!Time to React!
Time to React!
Ā 

More from Nikolas Burk

Next-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and PrismaNext-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and PrismaNikolas Burk
Ā 
Code-first GraphQL Server Development with Prisma
Code-first  GraphQL Server Development with PrismaCode-first  GraphQL Server Development with Prisma
Code-first GraphQL Server Development with PrismaNikolas Burk
Ā 
GraphQL & Prisma from Scratch
GraphQL & Prisma from ScratchGraphQL & Prisma from Scratch
GraphQL & Prisma from ScratchNikolas Burk
Ā 
GraphQL Schema Stitching with Prisma & Contentful
GraphQL Schema Stitching with Prisma & ContentfulGraphQL Schema Stitching with Prisma & Contentful
GraphQL Schema Stitching with Prisma & ContentfulNikolas Burk
Ā 
Managing GraphQL servers with AWS Fargate & Prisma Cloud
Managing GraphQL servers  with AWS Fargate & Prisma CloudManaging GraphQL servers  with AWS Fargate & Prisma Cloud
Managing GraphQL servers with AWS Fargate & Prisma CloudNikolas Burk
Ā 
Building GraphQL Servers with Node.JS & Prisma
Building GraphQL Servers with Node.JS & PrismaBuilding GraphQL Servers with Node.JS & Prisma
Building GraphQL Servers with Node.JS & PrismaNikolas Burk
Ā 
The GraphQL Ecosystem in 2018
The GraphQL Ecosystem in 2018The GraphQL Ecosystem in 2018
The GraphQL Ecosystem in 2018Nikolas Burk
Ā 
React & GraphQL
React & GraphQLReact & GraphQL
React & GraphQLNikolas Burk
Ā 
Building Serverless GraphQL Backends
Building Serverless GraphQL BackendsBuilding Serverless GraphQL Backends
Building Serverless GraphQL BackendsNikolas Burk
Ā 
GraphQL Subscriptions
GraphQL SubscriptionsGraphQL Subscriptions
GraphQL SubscriptionsNikolas Burk
Ā 
The Serverless GraphQL Backend Architecture
The Serverless GraphQL Backend ArchitectureThe Serverless GraphQL Backend Architecture
The Serverless GraphQL Backend ArchitectureNikolas Burk
Ā 
State Management & Unidirectional Data Flow
State Management & Unidirectional Data FlowState Management & Unidirectional Data Flow
State Management & Unidirectional Data FlowNikolas Burk
Ā 
Diving into GraphQL, React & Apollo
Diving into GraphQL, React & ApolloDiving into GraphQL, React & Apollo
Diving into GraphQL, React & ApolloNikolas Burk
Ā 
Authentication, Authorization & Error Handling with GraphQL
Authentication, Authorization & Error Handling with GraphQLAuthentication, Authorization & Error Handling with GraphQL
Authentication, Authorization & Error Handling with GraphQLNikolas Burk
Ā 
Building a Realtime Chat with React Native (Expo) & GraphQL Subscriptions
Building a Realtime Chat with React Native (Expo) & GraphQL Subscriptions Building a Realtime Chat with React Native (Expo) & GraphQL Subscriptions
Building a Realtime Chat with React Native (Expo) & GraphQL Subscriptions Nikolas Burk
Ā 
Building a Realtime Chat with React & GraphQL Subscriptions
Building a Realtime Chat with React & GraphQL Subscriptions Building a Realtime Chat with React & GraphQL Subscriptions
Building a Realtime Chat with React & GraphQL Subscriptions Nikolas Burk
Ā 
REST in Peace - Using GraphQL with Apollo on iOS
REST in Peace - Using GraphQL with Apollo on iOSREST in Peace - Using GraphQL with Apollo on iOS
REST in Peace - Using GraphQL with Apollo on iOSNikolas Burk
Ā 

More from Nikolas Burk (17)

Next-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and PrismaNext-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and Prisma
Ā 
Code-first GraphQL Server Development with Prisma
Code-first  GraphQL Server Development with PrismaCode-first  GraphQL Server Development with Prisma
Code-first GraphQL Server Development with Prisma
Ā 
GraphQL & Prisma from Scratch
GraphQL & Prisma from ScratchGraphQL & Prisma from Scratch
GraphQL & Prisma from Scratch
Ā 
GraphQL Schema Stitching with Prisma & Contentful
GraphQL Schema Stitching with Prisma & ContentfulGraphQL Schema Stitching with Prisma & Contentful
GraphQL Schema Stitching with Prisma & Contentful
Ā 
Managing GraphQL servers with AWS Fargate & Prisma Cloud
Managing GraphQL servers  with AWS Fargate & Prisma CloudManaging GraphQL servers  with AWS Fargate & Prisma Cloud
Managing GraphQL servers with AWS Fargate & Prisma Cloud
Ā 
Building GraphQL Servers with Node.JS & Prisma
Building GraphQL Servers with Node.JS & PrismaBuilding GraphQL Servers with Node.JS & Prisma
Building GraphQL Servers with Node.JS & Prisma
Ā 
The GraphQL Ecosystem in 2018
The GraphQL Ecosystem in 2018The GraphQL Ecosystem in 2018
The GraphQL Ecosystem in 2018
Ā 
React & GraphQL
React & GraphQLReact & GraphQL
React & GraphQL
Ā 
Building Serverless GraphQL Backends
Building Serverless GraphQL BackendsBuilding Serverless GraphQL Backends
Building Serverless GraphQL Backends
Ā 
GraphQL Subscriptions
GraphQL SubscriptionsGraphQL Subscriptions
GraphQL Subscriptions
Ā 
The Serverless GraphQL Backend Architecture
The Serverless GraphQL Backend ArchitectureThe Serverless GraphQL Backend Architecture
The Serverless GraphQL Backend Architecture
Ā 
State Management & Unidirectional Data Flow
State Management & Unidirectional Data FlowState Management & Unidirectional Data Flow
State Management & Unidirectional Data Flow
Ā 
Diving into GraphQL, React & Apollo
Diving into GraphQL, React & ApolloDiving into GraphQL, React & Apollo
Diving into GraphQL, React & Apollo
Ā 
Authentication, Authorization & Error Handling with GraphQL
Authentication, Authorization & Error Handling with GraphQLAuthentication, Authorization & Error Handling with GraphQL
Authentication, Authorization & Error Handling with GraphQL
Ā 
Building a Realtime Chat with React Native (Expo) & GraphQL Subscriptions
Building a Realtime Chat with React Native (Expo) & GraphQL Subscriptions Building a Realtime Chat with React Native (Expo) & GraphQL Subscriptions
Building a Realtime Chat with React Native (Expo) & GraphQL Subscriptions
Ā 
Building a Realtime Chat with React & GraphQL Subscriptions
Building a Realtime Chat with React & GraphQL Subscriptions Building a Realtime Chat with React & GraphQL Subscriptions
Building a Realtime Chat with React & GraphQL Subscriptions
Ā 
REST in Peace - Using GraphQL with Apollo on iOS
REST in Peace - Using GraphQL with Apollo on iOSREST in Peace - Using GraphQL with Apollo on iOS
REST in Peace - Using GraphQL with Apollo on iOS
Ā 

Recently uploaded

WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2
Ā 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
Ā 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...masabamasaba
Ā 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
Ā 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
Ā 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2
Ā 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
Ā 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2
Ā 
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...WSO2
Ā 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationJuha-Pekka Tolvanen
Ā 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
Ā 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp KrisztiƔn
Ā 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2
Ā 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
Ā 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
Ā 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
Ā 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2
Ā 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in sowetomasabamasaba
Ā 

Recently uploaded (20)

Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Ā 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
Ā 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
Ā 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
Ā 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
Ā 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
Ā 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
Ā 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
Ā 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
Ā 
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...
Ā 
Abortion Pills In Pretoria ](+27832195400*)[ šŸ„ Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ šŸ„ Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ šŸ„ Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ šŸ„ Women's Abortion Clinic In Pre...
Ā 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
Ā 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
Ā 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
Ā 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
Ā 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
Ā 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
Ā 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
Ā 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
Ā 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
Ā 

Getting Started with Relay Modern

  • 1.
  • 2.
  • 3. Nikolas Burk šŸ‘‹ Developer at Graphcool $ whoami @nikolasburk
  • 4. Launch Week šŸš€ Product Hunt > 1000 upvotesHacker News #1
  • 6. 1. Relay - A Brief History 2. Data Fetching 3. Mutations 4. More Features in Relay Modern Agenda @nikolasburk
  • 7. Relay - A Brief History @nikolasburk
  • 8. Relay - A Brief History @nikolasburk 01/2015 1st talk about Relay @React.js Conf 2015 2012 FB starts using GraphQL 02/2015 šŸ—£ Announcing Relay will be open-source 08/2015 Relay is open-source šŸŽ‰ 08/2016 šŸ—£ Announcing plans for ā€œRelay 2ā€ 04/2017 Introducing Relay Modern
  • 9. GraphQL Clients - homegrown by Facebook - main goal: performance - learning curve - community-driven - main goal: ļ¬‚exibility - easy-to-get-started @nikolasburk
  • 11. Traditional Data Fetching with REST 1. construct & send HTTP request (e.g. with fetch) 2. receive & parse server response 3. store data locally 4. display data in UI šŸ˜ @nikolasburk
  • 12. Declarative Data Fetching with GraphQL 1. describe data dependencies 2. display data in UI šŸ˜ @nikolasburk
  • 13. Relayā€™s core idea is to couple a view component with its data dependencies @nikolasburk
  • 16. class Post extends React.Component { render () { return ( <div> <img src={this.props.post.imageUrl} /> <div> {this.props.post.description} </div> </div> ) } } export default createFragmentContainer(Post, graphql` fragment Post_post on Post { id description imageUrl } `) Post.js @nikolasburk
  • 17. class Post extends React.Component { render () { return ( <div> <img src={this.props.post.imageUrl} /> <div> {this.props.post.description} </div> </div> ) } } export default createFragmentContainer(Post, graphql` fragment Post_post on Post { id description imageUrl } `) Post.js @nikolasburk
  • 18. class Post extends React.Component { render () { return ( <div> <img src={this.props.post.imageUrl} /> <div> {this.props.post.description} </div> </div> ) } } export default createFragmentContainer(Post, graphql` fragment Post_post on Post { id description imageUrl } `) Post.js @nikolasburk
  • 19. class Post extends React.Component { render () { return ( <div> <img src={this.props.post.imageUrl} /> <div> {this.props.post.description} </div> </div> ) } } export default createFragmentContainer(Post, graphql` fragment Post_post on Post { id description imageUrl } `) Post.js @nikolasburk
  • 20. class Post extends React.Component { render () { return ( <div> <img src={this.props.post.imageUrl} /> <div> {this.props.post.description} </div> </div> ) } } export default createFragmentContainer(Post, graphql` fragment Post_post on Post { id description imageUrl } `) Post.js @nikolasburk
  • 21. class Post extends React.Component { render () { return ( <div> <img src={this.props.post.imageUrl} /> <div> {this.props.post.description} </div> </div> ) } } export default createFragmentContainer(Post, graphql` fragment Post_post on Post { id description imageUrl } `) Post.js @nikolasburk
  • 22. export default createFragmentContainer(ListPage, graphql` fragment ListPage_viewer on Viewer { allPosts @connection(key: ā€œListPage_allPosts") { edges { node { ā€¦Post_post # from Post.js } } } } `) class ListPage extends React.Component { render () { return ( <div> {this.props.viewer.allPosts.edges.map(({node}) => <Post key={node.id} post={node} /> )} </div> ) } } ListPage.js @nikolasburk
  • 23. export default createFragmentContainer(ListPage, graphql` fragment ListPage_viewer on Viewer { allPosts @connection(key: ā€œListPage_allPosts") { edges { node { ...Post_post } } } } `) class ListPage extends React.Component { render () { return ( <div> {this.props.viewer.allPosts.edges.map(({node}) => <Post key={node.id} post={node} /> )} </div> ) } } ListPage.js @nikolasburk
  • 24. export default createFragmentContainer(ListPage, graphql` fragment ListPage_viewer on Viewer { allPosts @connection(key: ā€œListPage_allPosts") { edges { node { ...Post_post } } } } `) class ListPage extends React.Component { render () { return ( <div> {this.props.viewer.allPosts.edges.map(({node}) => <Post key={node.id} post={node} /> )} </div> ) } } ListPage.js @nikolasburk
  • 25. export default createFragmentContainer(ListPage, graphql` fragment ListPage_viewer on Viewer { allPosts @connection(key: ā€œListPage_allPosts") { edges { node { ...Post_post } } } } `) class ListPage extends React.Component { render () { return ( <div> {this.props.viewer.allPosts.edges.map(({node}) => <Post key={node.id} post={node} /> )} </div> ) } } ListPage.js @nikolasburk
  • 26. export default createFragmentContainer(ListPage, graphql` fragment ListPage_viewer on Viewer { allPosts @connection(key: ā€œListPage_allPosts") { edges { node { ...Post_post } } } } `) class ListPage extends React.Component { render () { return ( <div> {this.props.viewer.allPosts.edges.map(({node}) => <Post key={node.id} post={node} /> )} </div> ) } } ListPage.js @nikolasburk
  • 27. export default createFragmentContainer(ListPage, graphql` fragment ListPage_viewer on Viewer { allPosts @connection(key: "ListPage_allPosts") { edges { node { ...Post_post } } } } `) class ListPage extends React.Component { render () { return ( <div> {this.props.viewer.allPosts.edges.map(({node}) => <Post key={node.id} post={node} /> )} </div> ) } } ListPage.js @nikolasburk
  • 28. The QueryRenderer QueryRenderer is the root of a Relay tree. It takes a query, fetches the data and calls the render callback. @nikolasburk
  • 29. class App extends Component { render() { return ( <QueryRenderer environment={environment} query={AppAllPostQuery} render={({error, props}) => { if (error) { return <div>{error.message}</div> } else if (props) { return <ListPage viewer={props.viewer} /> } return <div>Loading</div> }} /> ) } } const AppAllPostQuery = graphql` query AppAllPostQuery { viewer { ā€¦ListPage_viewer } } ` App.js @nikolasburk
  • 30. class App extends Component { render() { return ( <QueryRenderer environment={environment} query={AppAllPostQuery} render={({error, props}) => { if (error) { return <div>{error.message}</div> } else if (props) { return <ListPage viewer={props.viewer} /> } return <div>Loading</div> }} /> ) } } const AppAllPostQuery = graphql` query AppAllPostQuery { viewer { ā€¦ListPage_viewer } } ` App.js @nikolasburk
  • 31. class App extends Component { render() { return ( <QueryRenderer environment={environment} query={AppAllPostQuery} render={({error, props}) => { if (error) { return <div>{error.message}</div> } else if (props) { return <ListPage viewer={props.viewer} /> } return <div>Loading</div> }} /> ) } } const AppAllPostQuery = graphql` query AppAllPostQuery { viewer { ā€¦ListPage_viewer # from ListPage.js } } ` App.js @nikolasburk
  • 32. class App extends Component { render() { return ( <QueryRenderer environment={environment} query={AppAllPostQuery} render={({error, props}) => { if (error) { return <div>{error.message}</div> } else if (props) { return <ListPage viewer={props.viewer} /> } return <div>Loading</div> }} /> ) } } const AppAllPostQuery = graphql` query AppAllPostQuery { viewer { ā€¦ListPage_viewer } } ` ListPage.js @nikolasburk
  • 33. class App extends Component { render() { return ( <QueryRenderer environment={environment} query={AppAllPostQuery} render={({error, props}) => { if (error) { return <div>{error.message}</div> } else if (props) { return <ListPage viewer={props.viewer} /> } return <div>Loading</div> }} /> ) } } const AppAllPostQuery = graphql` query AppAllPostQuery { viewer { ā€¦ListPage_viewer } } ` ListPage.js @nikolasburk
  • 34. class App extends Component { render() { return ( <QueryRenderer environment={environment} query={AppAllPostQuery} render={({error, props}) => { if (error) { return <div>{error.message}</div> } else if (props) { return <ListPage viewer={props.viewer} /> } return <div>Loading</div> }} /> ) } } const AppAllPostQuery = graphql` query AppAllPostQuery { viewer { ā€¦ListPage_viewer } } ` ListPage.js @nikolasburk
  • 35. class App extends Component { render() { return ( <QueryRenderer environment={environment} query={AppAllPostQuery} render={({error, props}) => { if (error) { return <div>{error.message}</div> } else if (props) { return <ListPage viewer={props.viewer} /> } return <div>Loading</div> }} /> ) } } const AppAllPostQuery = graphql` query AppAllPostQuery { viewer { ā€¦ListPage_viewer } } ` ListPage.js @nikolasburk
  • 37. Mutations in Relay Modern const {commitMutation} = require('react-relay') commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) @nikolasburk
  • 38. Mutations in Relay Modern commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) @nikolasburk
  • 39. Mutations in Relay Modern commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) @nikolasburk
  • 40. Mutations in Relay Modern commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) const mutation = graphql` mutation CreatePostMutation($input: CreatePostInput!) { createPost(input: $input) { post { id description imageUrl } } } ` @nikolasburk
  • 41. Mutations in Relay Modern commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, } ) @nikolasburk
  • 42. Mutations in Relay Modern commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) const variables = { input: { description: ā€œNice Sunsetā€, imageUrl: ā€œwww.example.org/sunset.jpgā€, } } @nikolasburk
  • 43. Mutations in Relay Modern commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, } ) @nikolasburk
  • 44. Mutations in Relay Modern commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, } ) @nikolasburk
  • 45. Updating the Cache commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) updater: (proxyStore) => { const createPostField = proxyStore.getRootField('createPost') const newPost = createPostField.getLinkedRecord('post') const viewerProxy = proxyStore.get(viewerId) const connection = ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts') ConnectionHandler.insertEdgeAfter(connection, newPost) } const mutation = graphql` mutation CreatePostMutation($input: CreatePostInput!) { createPost(input: $input) { post { id description imageUrl } } } ` @nikolasburk
  • 46. Updating the Cache commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) updater: (proxyStore) => { const createPostField = proxyStore.getRootField('createPost') const newPost = createPostField.getLinkedRecord('post') const viewerProxy = proxyStore.get(viewerId) const connection = ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts') ConnectionHandler.insertEdgeAfter(connection, newPost) } const mutation = graphql` mutation CreatePostMutation($input: CreatePostInput!) { createPost(input: $input) { post { id description imageUrl } } } ` @nikolasburk
  • 47. Updating the Cache commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) updater: (proxyStore) => { const createPostField = proxyStore.getRootField('createPost') const newPost = createPostField.getLinkedRecord('post') const viewerProxy = proxyStore.get(viewerId) const connection = ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts') ConnectionHandler.insertEdgeAfter(connection, newPost) } const mutation = graphql` mutation CreatePostMutation($input: CreatePostInput!) { createPost(input: $input) { post { id description imageUrl } } } ` @nikolasburk
  • 48. Updating the Cache commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) updater: (proxyStore) => { const createPostField = proxyStore.getRootField('createPost') const newPost = createPostField.getLinkedRecord('post') const viewerProxy = proxyStore.get(viewerId) const connection = ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts') ConnectionHandler.insertEdgeAfter(connection, newPost) } fragment ListPage_viewer on Viewer { allPosts @connection(key: "ListPage_allPosts") { edges { node { ...Post_post } } } } @nikolasburk
  • 49. Updating the Cache commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) updater: (proxyStore) => { const createPostField = proxyStore.getRootField('createPost') const newPost = createPostField.getLinkedRecord('post') const viewerProxy = proxyStore.get(viewerId) const connection = ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts') ConnectionHandler.insertEdgeAfter(connection, newPost) } fragment ListPage_viewer on Viewer { allPosts @connection(key: "ListPage_allPosts") { edges { node { ...Post_post } } } } @nikolasburk
  • 50. Mutations in Relay Modern commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, } ) @nikolasburk
  • 51. Updating the Cache (Optimistically) commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) optimisticUpdater: (proxyStore) => { const id = 'client:newPost:' + tempID++ const newPost = proxyStore.create(id, 'Post') newPost.setValue(description, 'description') newPost.setValue(imageUrl, 'imageUrl') const viewerProxy = proxyStore.get(viewerId) const connection = ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts') ConnectionHandler.insertEdgeAfter(connection, newPost) } @nikolasburk
  • 52. Updating the Cache (Optimistically) commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) optimisticUpdater: (proxyStore) => { const id = 'client:newPost:' + tempID++ const newPost = proxyStore.create(id, 'Post') newPost.setValue(description, 'description') newPost.setValue(imageUrl, 'imageUrl') const viewerProxy = proxyStore.get(viewerId) const connection = ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts') ConnectionHandler.insertEdgeAfter(connection, newPost) } @nikolasburk
  • 53. Updating the Cache (Optimistically) commitMutation( environment: Environment, config: { mutation: GraphQLTaggedNode, variables: Variables, onCompleted: (response) => void, onError: (error) => void, updater: (store) => void, optimisticUpdater: (store) => void, }, ) optimisticUpdater: (proxyStore) => { const id = 'client:newPost:' + tempID++ const newPost = proxyStore.create(id, 'Post') newPost.setValue(description, 'description') newPost.setValue(imageUrl, 'imageUrl') const viewerProxy = proxyStore.get(viewerId) const connection = ConnectionHandler.getConnection(viewerProxy, 'ListPage_allPosts') ConnectionHandler.insertEdgeAfter(connection, newPost) } @nikolasburk
  • 54. More Features in Relay Modern @nikolasburk
  • 55. The Relay Environment šŸŒ ā€¦.bundles together the conļ¬guration, cache storage, and network-handling that Relay needs in order to operate. const environment = new Environment({ network, store, }) @nikolasburk
  • 56. GraphQL Subscriptions āš” @nikolasburk ā€¦.allow to receive realtime events from the server.
  • 57. Client Schema Extensions šŸ’¼ @nikolasburk ā€¦.allow to store client state. extend type Post { hasViewerSeen: Boolean }
  • 58. Garbage Collection šŸ—‘ @nikolasburk ā€¦ removes objects from memory before the JS Garbage Collector runs.
  • 59. Compatibility Mode šŸŽÆ @nikolasburk ā€¦ allows to incrementally update an application from Relay Classic to Relay Modern.
  • 60. Resources šŸ“š ā€¢ Quickstart (Sample Code) https://github.com/graphcool-examples/react-graphql/tree/master/quickstart-with-relay-modern ā€¢ 1st talk about Relay @ React.JS Conf 2015 (Video) https://www.youtube.com/watch?v=9sc8Pyc51uU ā€¢ Introducing Relay and GraphQL (Article) https://facebook.github.io/react/blog/2015/02/20/introducing-relay-and-graphql.html ā€¢ Building Relay Modern (Article) https://wincent.com/blog/relay-modern ā€¢ Getting Started with Relay Modern (Tutorial) https://www.graph.cool/docs/tutorials/relay-modern-getting-started-woodito7ug/ @nikolasburk
  • 61. Community šŸ™Œ ā€¢ slack.graph.cool (> 2000 members) ā€¢ GraphQL Weekly Newsletter ā€¢ GraphQL Radio Podcast @nikolasburk
  • 63. Thank you! šŸ™‡ ā€¦ any questions? @nikolasburk