SlideShare a Scribd company logo
Missing Pages:
ReactJS/Flux/GraphQL/RelayJS
Khor, @neth_6, re:Culture
Shed light on assumptions/details
glossed over in FB’s docs
Agenda
● Using pure Flux
● GraphQL
○ Sans RelayJS
○ Setup GraphQL on non-NodeJS servers
● RelayJS
○ Revisiting ReactJS: Reduce coupling, increase reusability
○ What RelayJS Brings to GraphQL
○ Setup RelayJS/GraphQL on non-NodeJS servers
React Family: In a Few Words ...
● ReactJS: UI data & rendering
● Flux: Data flow & code organization
● GraphQL: Single API endpoint data retrieval
● RelayJS: React component data declaration & co-location
GraphQL: Sans RelayJS
GraphQL
I speak GraphQL
API Endpoint
Single Endpoint can Deliver all data
store(email: “admin@abc.com”) {
name: ‘Hello Shop’,
address: ‘1-3-1 Aoyama’
categories: [
{
name: ‘Sporting Goods’,
products: [
{ name: ‘Football’, price: 20, stock: 50 },
{ name: ‘Baseball’, price: 5, stock: 30 },
…
],
...
}, …
],
}
GraphQL (cont.)
API Endpoint
query {
store(email: "admin@abc.com") {
name,
address
}
}
GraphQL (cont.)
API Endpoint
query {
store(email: "admin@abc.com") {
name,
address
}
}
store(email: “admin@abc.com”) {
name: ‘Hello Shop’,
address: ‘1-3-1 Aoyama’
}
Welcome to Hello Shop
Visit us at 1-3-1 Aoyama
Or shop online
GraphQL (cont.)
API Endpoint
query {
store(email: "admin@abc.com") {
categories {
name,
products {
name, price, stock
}
}
}
}
store {
categories: [
{ name: ‘Sporting Goods’,
products: [
{ name: ‘Football’, price:, stock: 50 }, …
}, ...
]
}
Hello Shop
GraphQL (cont.)
API Endpoint
query {
store(email: "admin@abc.com") {
categories {
name,
products {
name, price, stock
}
}
}
}
store {
categories: [
{ name: ‘Sporting Goods’,
products: [
{ name: ‘Football’, price:, stock: 50 }, …
}, ...
]
}
Single
endpoint
Hierarchical
data query
Client-specified
query
Data in 1
round-trip
GraphQL: Setup
GraphQL: Like all Client-Server
Browser
http(s)
Any Server
GraphQL: Over HTTP(S)
Browser
GraphQL
Server
Bundled
JS
GraphQL
over
http(s), etc.
Any Server
GraphQL Over http(s)
GraphQL over http
GraphQL: Enabling the Server
Browser
GraphQL
Server
Bundled
JS
GraphQL
over
http(s), etc.
Any Server
Server
Libraries
graphql
GraphQL
Schema
in Hash
GraphQL: JS Code
Browser
GraphQL
Server
Bundled
JS
Bundled
JS
Any Server
GraphQL
over
http(s), etc.
Server
Libraries
graphql
GraphQL
Schema
in Hash
GraphQL: Required JS Libraries
Browser
GraphQL
Server
Bundled
JS
Bundled
JS
Any Server
JS Libraries
react
react-dom
graphql
GraphQL
over
http(s), etc.
Server
Libraries
graphql
GraphQL
Schema
in Hash
GraphQL: Bundling Your JS Code
Browser
GraphQL
Server
Bundled
JS
Bundled
JS
Any Server
JS Libraries
react
react-dom
graphql
GraphQL
over
http(s), etc.
Server
Libraries
graphql
Your
JS
browserify/w
ebpackGraphQL
Schema
in Hash
ReactJS (Review)
ReactJS
● Single-Page Application (SPA)
Courtesy: https://facebook.github.io/react/docs/thinking-in-react.html
Hello Shop
ReactJS (cont.)
● Single-Page Application (SPA)
● Cascading Views
Hello Shop
ReactJS (cont.)
● Single-Page Application (SPA)
● Cascading Views
Hello Shop
React (cont.)
● Single-Page Application (SPA)
● Cascading Views
Hello Shop
Hierarchical Views => GraphQL Hierarchical Data
ReactJS (cont.)
Abstraction
Each ReactJS element knows:
● The data it needs
● How to render itself with HTML fragments
● The data it passes to its children
React (cont.)
● Single-Page Application (SPA)
● Cascading Views
Fetch
Data
Hello Shop
React (cont.)
● Single-Page Application (SPA)
● Cascading Views
Hello Shop
React (cont.)
● Single-Page Application (SPA)
● Cascading Views
Hello Shop
Passing Data to Children
this.props = {
store:
name: ‘Hello Shop’
categories: [
{
name: 'Sporting Goods',
items: [
{ name: 'Football', price: … }
…
],
},
...
],
},
}
Use Data & Render
this.props.store.name
Pass Down
this.props.store.categories
Not so Loose Coupling, Not so High Reuse
● Parent needs to know about child’s data
○ Need to fetch data for children
○ Need to pass correct data to children
render() {
return (
<Store>{this.props.store} />
<Categories categories={this.props.store.categories} />
)
}
RelayJS: Component-Data Co-location
Reduce coupling, increase reusability
GraphQL
I speak GraphQL
API Endpoint
Single Endpoint can Deliver all data
store(email: “admin@abc.com”) {
name: ‘Hello Shop’,
address: ‘1-3-1 Aoyama’
categories: [
{
name: ‘Sporting Goods’,
products: [
{ name: ‘Football’, price: 20, stock: 50 },
{ name: ‘Baseball’, price: 5, stock: 30 },
…
],
...
}, …
],
}
Sample App: Refresh your Memory
Hello Shop
Sample App: Simplified
Hello Shop
RelayJS: Component & Data Co-location
store(email: “admin@abc.com”) {
name: ‘Hello Shop’,
address: ‘1-3-1 Aoyama’
categories: [
{
name: ‘Sporting Goods’,
products: [
{ name: ‘Football’, price: 20, stock: 50 },
{ name: ‘Baseball’, price: 5, stock: 30 },
…
],
...
}, …
],
}
fragment on Store {
name,
address
}
Hello Shop
store(email: “admin@abc.com”) {
name: ‘Hello Shop’,
address: ‘1-3-1 Aoyama’
categories: [
{
name: ‘Sporting Goods’,
products: [
{ name: ‘Football’, price: 20, stock: 50 },
{ name: ‘Baseball’, price: 5, stock: 30 },
…
],
...
}, …
],
}
fragment on Store {
categories {
name,
products,
}
}
RelayJS: Component & Data Co-location
store(email: “admin@abc.com”) {
name: ‘Hello Shop’,
address: ‘1-3-1 Aoyama’
categories: [
{
name: ‘Sporting Goods’,
products: [
{ name: ‘Football’, price: 20, stock: 50 },
{ name: ‘Baseball’, price: 5, stock: 30 },
…
],
...
}, …
],
}
Hello Shop
RelayJS will fetch
UNION of data
Passing Data to Children
this.props = {
store:
name: ‘Hello Shop’
categories: [
{
name: 'Sporting Goods',
items: [
{ name: 'Football', price: … }
…
],
},
...
],
},
}
Use Data & Render
this.props.store.name
Pass Down
this.props.store.categories
Not so Loose Coupling, Not so High Reuse
● Parent needs to need NOT know about child’s data
○ Need to fetch data for children
○ Need to pass correct data to children
render() {
return (
<Store>{this.props.store} />
<Categories categories={this.props.store.categories} />
)
}
RelayJS: What it Brings to GraphQL
Why RelayJS?
● Usable features:
○ Component-Data Co-location
○ Connection Id: Data re-fetching
○ Connections: One-to-Many Relationships/Pagination
○ Mutations: Modified data auto-updates affected React components
● Implicit features:
○ Auto-fetch declared data (no AJAX code)
○ Caching, batching data
● Bells & Whistles:
○ Show spinner, etc. during loading
○ Show error message, etc., if data fetch fail
○ Optimistic UI updates
RelayJS: Setup
RelayJS: Component-Data Co-location
Browser
GraphQL
/RelayJS
Server
Bundled
JSAny Server
JS Libraries
react
react-dom
react-relay
babelify-relay-
plugin
babelify
RelayJS
containers
calling
GraphQL
over
http(s), etc.
graphql
Server
Libraries
graphql
Your
JS with
Relay.QL
browserify/w
ebpack
GraphQL
Schema
in JSON
Bundled
JS
GraphQL
Schema
in Hash
Converter
graphql-relay
References
● Articles
○ GraphQL/RelayJS (non NodeJS): https://medium.com/@khor/relay-facebook-on-rails-8b4af2057152
○ Pure ‘Flux’ (non NodeJS): https://medium.com/@khor/back-to-front-rails-to-facebook-s-flux-ae815f81b16c
● Starter-kit
○ Rails: https://github.com/nethsix/relay-on-rails
● Choices: React, React (with Container), Flux/Redux, GraphQL/RelayJS
○ Shared by @koba04 - http://andrewhfarmer.com/react-ajax-best-practices/
● Follow: @neth_6, @reculture_us
Thank you:
● All for coming!
● Toru for invite!
● Facebook for tech & engineers!
Flux: The ‘pure’ version
Todo App
New Todo
Create
Todo #1
Todo #2
Created Todo List
Todo App: React with AJAX
Render
render() {
return (_.map(
this.state.todos,
(e) => { return <div>{e}</div> })
)
}
Get Todos
componentDidMount() {
$.ajax {
url: …GET
success: (data) => {
this.setState(data);
}
}
}
Add Todo
onAddTodo() {
$.ajax {
url: …POST
success: (data) => {
this.setState(data);
}
}
}
Edit Todo
onEditTodo() {
$.ajax {
url: …PUT
success: (data) => {
this.setState(data);
}
}
}
. . .
Data
this.setState = {
todos: [
‘Todo #1’, ‘Todo #2’
]
}
Flux: Code Organization
Views
Actions
Get Todos
getTodot() {
$.ajax {
url: …GET
success: (data) => {
this.setState(data);
}
}
}
Add Todo
addToto() {
$.ajax {
url: …POST
success: (data) => {
this.setState(data);
}
}
}
Edit Todo
editTodo() {
$.ajax {
url: …PUT
success: (data) => {
this.setState(data);
}
}
}
this.setState = {
todos: [
‘Todo #1’, ‘Todo #2’
]
}
Flux: Data Flow
Views
Actions
Get Todos
getTodos() {
$.ajax {
url: …GET
success: (data) => {
this.setState(data);
}
}
}
Add Todo
addTodo() {
$.ajax {
url: …POST
success: (data) => {
this.setState(data);
}
}
}
Edit Todo
editTodo() {
$.ajax {
url: …PUT
success: (data) => {
this.setState(data);
}
}
}
this.setState = {
todos: [
‘Todo #1’, ‘Todo #2’
]
}
Dispatcher
● Throttles one Action at a time
● waitsFor()
Get Todos
getTodot() {
$.ajax {
url: …GET
success: (data) => {
this.setState(data);
}
}
}
Add Todo
addToto() {
$.ajax {
url: …POST
success: (data) => {
this.setState(data);
}
}
}
Edit Todo
editTodo() {
$.ajax {
url: …PUT
success: (data) => {
this.setState(data);
}
}
}
Flux: Data Flow
Views
this.setState = {
todos: [
‘Todo #1’, ‘Todo #2’
]
users: [
‘User #1, ‘User #2’
]
}
Actions
Views
Get Users
getUsers() {
$.ajax {
url: …GET
success: (data) => {
this.setState(data);
}
}
}
Add User
addUser() {
$.ajax {
url: …POST
success: (data) => {
this.setState(data);
}
}
}
Edit User
editUser() {
$.ajax {
url: …PUT
success: (data) => {
this.setState(data);
}
}
}
Dispatcher
● Throttles one Action at a time
● waitsFor()
Flux: Data Flow
Views
Actions
Views
Dispatcher
● Throttles one Action at a time
● waitsFor()
Todo Store
User Store
register
this.setState = {
todos: [
‘Todo #1’, ‘Todo #2’
]
} this.setState = {
users: [
‘User #1, ‘User #2’
]
}
register
Get Todos
getTodot() {
$.ajax {
url: …GET
success: (data) => {
this.setState(data);
}
}
}
Add Todo
addToto() {
$.ajax {
url: …POST
success: (data) => {
this.setState(data);
}
}
}
Edit Todo
editTodo() {
$.ajax {
url: …PUT
success: (data) => {
this.setState(data);
}
}
}
Get Users
getUsers() {
$.ajax {
url: …GET
success: (data) => {
this.setState(data);
}
}
}
Add User
addUser() {
$.ajax {
url: …POST
success: (data) => {
this.setState(data);
}
}
}
Edit User
editUser() {
$.ajax {
url: …PUT
success: (data) => {
this.setState(data);
}
}
}
Flux: Data Flow
Views
Actions
Views
Dispatcher
● Throttles one Action at a time
● waitsFor()
Todo Store
User Store
listen
this.setState = {
todos: [
‘Todo #1’, ‘Todo #2’
]
} this.setState = {
users: [
‘User #1, ‘User #2’
]
}
listen
listen
Todo Actions
listen
User Actions
Get Todos
getTodot() {
$.ajax {
url: …GET
success: (data) => {
this.setState(data);
}
}
}
Add Todo
addToto() {
$.ajax {
url: …POST
success: (data) => {
this.setState(data);
}
}
}
Edit Todo
editTodo() {
$.ajax {
url: …PUT
success: (data) => {
this.setState(data);
}
}
}
Get Users
getUsers() {
$.ajax {
url: …GET
success: (data) => {
this.setState(data);
}
}
}
Add User
addUser() {
$.ajax {
url: …POST
success: (data) => {
this.setState(data);
}
}
}
Edit User
editUser() {
$.ajax {
url: …PUT
success: (data) => {
this.setState(data);
}
}
}
Flux
Courtesy: http://fluxxor.com/what-is-flux.html
Flux: Additional Slides
Todo App: React with props
Data
const _props = {
todos: [
‘Todo #1’, ‘Todo #2’
]
}
Code
render() {
return (_.map(
this.props.todos,
(e) => { return <div>{e}</div> })
)
}
Initialize
const _root = document.findElementById(‘root’);
ReactDOM.render(<TodoApp {..._props} />, _root);
Todo App with Flux
Data
const _props = {
todos: [
‘Todo #1’, ‘Todo #2’
]
}
Code
render() {
return (_.map(
this.props.todos,
(e) => { return <div>{e}</div> })
)
}
Initialize
const _root = document.findElementById(‘root’);
ReactDOM.render(<TodoApp {..._props} />, _root);
Action Creator Trigger
<form>
<input id=’todo-text’ type=’text’ />
<button onClick=TodoActions.create($(‘#todo-text’).val())>Create</button>
</form>
Action Creator
TodoActions: {
create: function(text) {
// Take some action, e.g., call REST API
AppDispatcher.dispatch({
actionType: TodoConstants.TODO_CREATE, // Basically ‘create’
text: text
});
},
….
}
Store
AppDispatcher.register(function(action) { // action is passed in by Action Creator
var event = action.event;
switch(action.actionType) {
case TodoConstants.TODO_CREATE:
// Do whatever, e.g., update local store data or fetch fresh data from server
TodoStore.emitChange();
break;
….
}
}
register
Store (cont.)
var TodoStore = assign({}, EventEmitter.prototype, {
// EventEmitter provides emit, on, removeListener, etc. methods
addChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback);
},
removeChangeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
},
emitChange: function() {
this.emit(CHANGE_EVENT);
},
...
}
register
Controller-View
// This is where React is used
var TodoApp = React.createClass({
componentDidMount: function() {
TodoStore.addChangeListener(this._onChange);
},
componentWillUnmount: function() {
TodoStore.removeChangeListener(this._onChange);
},
_onChange: function() {
this.setState(TodoStore.getData());
},
...
}
register

More Related Content

PDF
From Back to Front: Rails To React Family
PDF
Rails + Webpack
PPTX
HTL(Sightly) - All you need to know
PPTX
Sightly - Part 2
PDF
jQuery and Rails: Best Friends Forever
PDF
Hands On With Rich Faces 4 - JavaOne 2010
PPT
jQuery and AJAX with Rails
PDF
Angular2 Development for Java developers
From Back to Front: Rails To React Family
Rails + Webpack
HTL(Sightly) - All you need to know
Sightly - Part 2
jQuery and Rails: Best Friends Forever
Hands On With Rich Faces 4 - JavaOne 2010
jQuery and AJAX with Rails
Angular2 Development for Java developers

What's hot (20)

PPT
A quick guide to Css and java script
PDF
Introduction to Sightly
KEY
Templates
PDF
React Native Workshop - React Alicante
PDF
JavaFX in Action (devoxx'16)
PDF
JavaFX – 10 things I love about you
PPTX
e-suap - client technologies- english version
PPTX
Angular Js Advantages - Complete Reference
PDF
How we improved performance at Mixbook
PDF
Unobtrusive JavaScript
PDF
An Introduction to ReactJS
PPTX
React + Redux Introduction
PDF
Module 3: Working with the DOM and jQuery
PPTX
AEM - Client Libraries
PDF
SproutCore and the Future of Web Apps
PPTX
ReactJs presentation
PDF
Intro to ReactJS
PPTX
Java script Session No 1
PPTX
SharePoint Saturday St. Louis - SharePoint & jQuery
PDF
Introduction to AngularJS By Bharat Makwana
A quick guide to Css and java script
Introduction to Sightly
Templates
React Native Workshop - React Alicante
JavaFX in Action (devoxx'16)
JavaFX – 10 things I love about you
e-suap - client technologies- english version
Angular Js Advantages - Complete Reference
How we improved performance at Mixbook
Unobtrusive JavaScript
An Introduction to ReactJS
React + Redux Introduction
Module 3: Working with the DOM and jQuery
AEM - Client Libraries
SproutCore and the Future of Web Apps
ReactJs presentation
Intro to ReactJS
Java script Session No 1
SharePoint Saturday St. Louis - SharePoint & jQuery
Introduction to AngularJS By Bharat Makwana
Ad

Similar to Tokyo React.js #3: Missing Pages: ReactJS/Flux/GraphQL/RelayJS (20)

PDF
Overview of GraphQL & Clients
PDF
Redux vs Alt
PDF
Data models in Angular 1 & 2
PPTX
Agile data presentation 3 - cambridge
PPTX
Progressive Enhancment with Rails and React
PDF
ReactJS presentation
PDF
Full Stack Toronto - the 3R Stack
PDF
React table tutorial project setup, use table, and usefilter
PDF
Elixir, GraphQL and Vue.js
PDF
Crossing platforms with JavaScript & React
PDF
Connect.js - Exploring React.Native
PPTX
Building complex User Interfaces with Sitecore and React
PDF
GraphQL Search
PDF
Deck 893ff61f-1fb8-4e15-a379-775dfdbcee77-7-14-55-78-171-219-304-310-388 (1)
PDF
Getting Started with Relay Modern
PPTX
PDF
PPTX
Developing RESTful Services in .NET
PDF
Egghead redux-cheat-sheet-3-2-1
PDF
Advanced redux
Overview of GraphQL & Clients
Redux vs Alt
Data models in Angular 1 & 2
Agile data presentation 3 - cambridge
Progressive Enhancment with Rails and React
ReactJS presentation
Full Stack Toronto - the 3R Stack
React table tutorial project setup, use table, and usefilter
Elixir, GraphQL and Vue.js
Crossing platforms with JavaScript & React
Connect.js - Exploring React.Native
Building complex User Interfaces with Sitecore and React
GraphQL Search
Deck 893ff61f-1fb8-4e15-a379-775dfdbcee77-7-14-55-78-171-219-304-310-388 (1)
Getting Started with Relay Modern
Developing RESTful Services in .NET
Egghead redux-cheat-sheet-3-2-1
Advanced redux
Ad

More from Khor SoonHin (6)

PDF
The Many Flavors of OAuth - Understand Everything About OAuth2
PDF
Gentlest Introduction to Tensorflow - Part 3
PDF
RMSLE cost function
PDF
Gentlest Introduction to Tensorflow - Part 2
PDF
Gentlest Introduction to Tensorflow
PDF
Tokyo React.js #3 Meetup (ja): Missing Pages: ReactJS/GraphQL/RelayJS
The Many Flavors of OAuth - Understand Everything About OAuth2
Gentlest Introduction to Tensorflow - Part 3
RMSLE cost function
Gentlest Introduction to Tensorflow - Part 2
Gentlest Introduction to Tensorflow
Tokyo React.js #3 Meetup (ja): Missing Pages: ReactJS/GraphQL/RelayJS

Recently uploaded (20)

PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Empathic Computing: Creating Shared Understanding
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Electronic commerce courselecture one. Pdf
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Approach and Philosophy of On baking technology
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Encapsulation_ Review paper, used for researhc scholars
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PDF
A comparative analysis of optical character recognition models for extracting...
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Review of recent advances in non-invasive hemoglobin estimation
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Chapter 3 Spatial Domain Image Processing.pdf
Per capita expenditure prediction using model stacking based on satellite ima...
Unlocking AI with Model Context Protocol (MCP)
Empathic Computing: Creating Shared Understanding
Reach Out and Touch Someone: Haptics and Empathic Computing
Electronic commerce courselecture one. Pdf
MYSQL Presentation for SQL database connectivity
Approach and Philosophy of On baking technology
Assigned Numbers - 2025 - Bluetooth® Document
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Advanced methodologies resolving dimensionality complications for autism neur...
Encapsulation_ Review paper, used for researhc scholars
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
A comparative analysis of optical character recognition models for extracting...
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Review of recent advances in non-invasive hemoglobin estimation
The AUB Centre for AI in Media Proposal.docx
Spectral efficient network and resource selection model in 5G networks
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...

Tokyo React.js #3: Missing Pages: ReactJS/Flux/GraphQL/RelayJS

  • 2. Shed light on assumptions/details glossed over in FB’s docs
  • 3. Agenda ● Using pure Flux ● GraphQL ○ Sans RelayJS ○ Setup GraphQL on non-NodeJS servers ● RelayJS ○ Revisiting ReactJS: Reduce coupling, increase reusability ○ What RelayJS Brings to GraphQL ○ Setup RelayJS/GraphQL on non-NodeJS servers
  • 4. React Family: In a Few Words ... ● ReactJS: UI data & rendering ● Flux: Data flow & code organization ● GraphQL: Single API endpoint data retrieval ● RelayJS: React component data declaration & co-location
  • 6. GraphQL I speak GraphQL API Endpoint Single Endpoint can Deliver all data store(email: “admin@abc.com”) { name: ‘Hello Shop’, address: ‘1-3-1 Aoyama’ categories: [ { name: ‘Sporting Goods’, products: [ { name: ‘Football’, price: 20, stock: 50 }, { name: ‘Baseball’, price: 5, stock: 30 }, … ], ... }, … ], }
  • 7. GraphQL (cont.) API Endpoint query { store(email: "admin@abc.com") { name, address } }
  • 8. GraphQL (cont.) API Endpoint query { store(email: "admin@abc.com") { name, address } } store(email: “admin@abc.com”) { name: ‘Hello Shop’, address: ‘1-3-1 Aoyama’ } Welcome to Hello Shop Visit us at 1-3-1 Aoyama Or shop online
  • 9. GraphQL (cont.) API Endpoint query { store(email: "admin@abc.com") { categories { name, products { name, price, stock } } } } store { categories: [ { name: ‘Sporting Goods’, products: [ { name: ‘Football’, price:, stock: 50 }, … }, ... ] } Hello Shop
  • 10. GraphQL (cont.) API Endpoint query { store(email: "admin@abc.com") { categories { name, products { name, price, stock } } } } store { categories: [ { name: ‘Sporting Goods’, products: [ { name: ‘Football’, price:, stock: 50 }, … }, ... ] } Single endpoint Hierarchical data query Client-specified query Data in 1 round-trip
  • 12. GraphQL: Like all Client-Server Browser http(s) Any Server
  • 15. GraphQL: Enabling the Server Browser GraphQL Server Bundled JS GraphQL over http(s), etc. Any Server Server Libraries graphql GraphQL Schema in Hash
  • 16. GraphQL: JS Code Browser GraphQL Server Bundled JS Bundled JS Any Server GraphQL over http(s), etc. Server Libraries graphql GraphQL Schema in Hash
  • 17. GraphQL: Required JS Libraries Browser GraphQL Server Bundled JS Bundled JS Any Server JS Libraries react react-dom graphql GraphQL over http(s), etc. Server Libraries graphql GraphQL Schema in Hash
  • 18. GraphQL: Bundling Your JS Code Browser GraphQL Server Bundled JS Bundled JS Any Server JS Libraries react react-dom graphql GraphQL over http(s), etc. Server Libraries graphql Your JS browserify/w ebpackGraphQL Schema in Hash
  • 20. ReactJS ● Single-Page Application (SPA) Courtesy: https://facebook.github.io/react/docs/thinking-in-react.html Hello Shop
  • 21. ReactJS (cont.) ● Single-Page Application (SPA) ● Cascading Views Hello Shop
  • 22. ReactJS (cont.) ● Single-Page Application (SPA) ● Cascading Views Hello Shop
  • 23. React (cont.) ● Single-Page Application (SPA) ● Cascading Views Hello Shop Hierarchical Views => GraphQL Hierarchical Data
  • 24. ReactJS (cont.) Abstraction Each ReactJS element knows: ● The data it needs ● How to render itself with HTML fragments ● The data it passes to its children
  • 25. React (cont.) ● Single-Page Application (SPA) ● Cascading Views Fetch Data Hello Shop
  • 26. React (cont.) ● Single-Page Application (SPA) ● Cascading Views Hello Shop
  • 27. React (cont.) ● Single-Page Application (SPA) ● Cascading Views Hello Shop
  • 28. Passing Data to Children this.props = { store: name: ‘Hello Shop’ categories: [ { name: 'Sporting Goods', items: [ { name: 'Football', price: … } … ], }, ... ], }, } Use Data & Render this.props.store.name Pass Down this.props.store.categories
  • 29. Not so Loose Coupling, Not so High Reuse ● Parent needs to know about child’s data ○ Need to fetch data for children ○ Need to pass correct data to children render() { return ( <Store>{this.props.store} /> <Categories categories={this.props.store.categories} /> ) }
  • 30. RelayJS: Component-Data Co-location Reduce coupling, increase reusability
  • 31. GraphQL I speak GraphQL API Endpoint Single Endpoint can Deliver all data store(email: “admin@abc.com”) { name: ‘Hello Shop’, address: ‘1-3-1 Aoyama’ categories: [ { name: ‘Sporting Goods’, products: [ { name: ‘Football’, price: 20, stock: 50 }, { name: ‘Baseball’, price: 5, stock: 30 }, … ], ... }, … ], }
  • 32. Sample App: Refresh your Memory Hello Shop
  • 34. RelayJS: Component & Data Co-location store(email: “admin@abc.com”) { name: ‘Hello Shop’, address: ‘1-3-1 Aoyama’ categories: [ { name: ‘Sporting Goods’, products: [ { name: ‘Football’, price: 20, stock: 50 }, { name: ‘Baseball’, price: 5, stock: 30 }, … ], ... }, … ], } fragment on Store { name, address } Hello Shop
  • 35. store(email: “admin@abc.com”) { name: ‘Hello Shop’, address: ‘1-3-1 Aoyama’ categories: [ { name: ‘Sporting Goods’, products: [ { name: ‘Football’, price: 20, stock: 50 }, { name: ‘Baseball’, price: 5, stock: 30 }, … ], ... }, … ], } fragment on Store { categories { name, products, } } RelayJS: Component & Data Co-location
  • 36. store(email: “admin@abc.com”) { name: ‘Hello Shop’, address: ‘1-3-1 Aoyama’ categories: [ { name: ‘Sporting Goods’, products: [ { name: ‘Football’, price: 20, stock: 50 }, { name: ‘Baseball’, price: 5, stock: 30 }, … ], ... }, … ], } Hello Shop RelayJS will fetch UNION of data
  • 37. Passing Data to Children this.props = { store: name: ‘Hello Shop’ categories: [ { name: 'Sporting Goods', items: [ { name: 'Football', price: … } … ], }, ... ], }, } Use Data & Render this.props.store.name Pass Down this.props.store.categories
  • 38. Not so Loose Coupling, Not so High Reuse ● Parent needs to need NOT know about child’s data ○ Need to fetch data for children ○ Need to pass correct data to children render() { return ( <Store>{this.props.store} /> <Categories categories={this.props.store.categories} /> ) }
  • 39. RelayJS: What it Brings to GraphQL
  • 40. Why RelayJS? ● Usable features: ○ Component-Data Co-location ○ Connection Id: Data re-fetching ○ Connections: One-to-Many Relationships/Pagination ○ Mutations: Modified data auto-updates affected React components ● Implicit features: ○ Auto-fetch declared data (no AJAX code) ○ Caching, batching data ● Bells & Whistles: ○ Show spinner, etc. during loading ○ Show error message, etc., if data fetch fail ○ Optimistic UI updates
  • 42. RelayJS: Component-Data Co-location Browser GraphQL /RelayJS Server Bundled JSAny Server JS Libraries react react-dom react-relay babelify-relay- plugin babelify RelayJS containers calling GraphQL over http(s), etc. graphql Server Libraries graphql Your JS with Relay.QL browserify/w ebpack GraphQL Schema in JSON Bundled JS GraphQL Schema in Hash Converter graphql-relay
  • 43. References ● Articles ○ GraphQL/RelayJS (non NodeJS): https://medium.com/@khor/relay-facebook-on-rails-8b4af2057152 ○ Pure ‘Flux’ (non NodeJS): https://medium.com/@khor/back-to-front-rails-to-facebook-s-flux-ae815f81b16c ● Starter-kit ○ Rails: https://github.com/nethsix/relay-on-rails ● Choices: React, React (with Container), Flux/Redux, GraphQL/RelayJS ○ Shared by @koba04 - http://andrewhfarmer.com/react-ajax-best-practices/ ● Follow: @neth_6, @reculture_us
  • 44. Thank you: ● All for coming! ● Toru for invite! ● Facebook for tech & engineers!
  • 46. Todo App New Todo Create Todo #1 Todo #2 Created Todo List
  • 47. Todo App: React with AJAX Render render() { return (_.map( this.state.todos, (e) => { return <div>{e}</div> }) ) } Get Todos componentDidMount() { $.ajax { url: …GET success: (data) => { this.setState(data); } } } Add Todo onAddTodo() { $.ajax { url: …POST success: (data) => { this.setState(data); } } } Edit Todo onEditTodo() { $.ajax { url: …PUT success: (data) => { this.setState(data); } } } . . . Data this.setState = { todos: [ ‘Todo #1’, ‘Todo #2’ ] }
  • 48. Flux: Code Organization Views Actions Get Todos getTodot() { $.ajax { url: …GET success: (data) => { this.setState(data); } } } Add Todo addToto() { $.ajax { url: …POST success: (data) => { this.setState(data); } } } Edit Todo editTodo() { $.ajax { url: …PUT success: (data) => { this.setState(data); } } } this.setState = { todos: [ ‘Todo #1’, ‘Todo #2’ ] }
  • 49. Flux: Data Flow Views Actions Get Todos getTodos() { $.ajax { url: …GET success: (data) => { this.setState(data); } } } Add Todo addTodo() { $.ajax { url: …POST success: (data) => { this.setState(data); } } } Edit Todo editTodo() { $.ajax { url: …PUT success: (data) => { this.setState(data); } } } this.setState = { todos: [ ‘Todo #1’, ‘Todo #2’ ] } Dispatcher ● Throttles one Action at a time ● waitsFor()
  • 50. Get Todos getTodot() { $.ajax { url: …GET success: (data) => { this.setState(data); } } } Add Todo addToto() { $.ajax { url: …POST success: (data) => { this.setState(data); } } } Edit Todo editTodo() { $.ajax { url: …PUT success: (data) => { this.setState(data); } } } Flux: Data Flow Views this.setState = { todos: [ ‘Todo #1’, ‘Todo #2’ ] users: [ ‘User #1, ‘User #2’ ] } Actions Views Get Users getUsers() { $.ajax { url: …GET success: (data) => { this.setState(data); } } } Add User addUser() { $.ajax { url: …POST success: (data) => { this.setState(data); } } } Edit User editUser() { $.ajax { url: …PUT success: (data) => { this.setState(data); } } } Dispatcher ● Throttles one Action at a time ● waitsFor()
  • 51. Flux: Data Flow Views Actions Views Dispatcher ● Throttles one Action at a time ● waitsFor() Todo Store User Store register this.setState = { todos: [ ‘Todo #1’, ‘Todo #2’ ] } this.setState = { users: [ ‘User #1, ‘User #2’ ] } register Get Todos getTodot() { $.ajax { url: …GET success: (data) => { this.setState(data); } } } Add Todo addToto() { $.ajax { url: …POST success: (data) => { this.setState(data); } } } Edit Todo editTodo() { $.ajax { url: …PUT success: (data) => { this.setState(data); } } } Get Users getUsers() { $.ajax { url: …GET success: (data) => { this.setState(data); } } } Add User addUser() { $.ajax { url: …POST success: (data) => { this.setState(data); } } } Edit User editUser() { $.ajax { url: …PUT success: (data) => { this.setState(data); } } }
  • 52. Flux: Data Flow Views Actions Views Dispatcher ● Throttles one Action at a time ● waitsFor() Todo Store User Store listen this.setState = { todos: [ ‘Todo #1’, ‘Todo #2’ ] } this.setState = { users: [ ‘User #1, ‘User #2’ ] } listen listen Todo Actions listen User Actions Get Todos getTodot() { $.ajax { url: …GET success: (data) => { this.setState(data); } } } Add Todo addToto() { $.ajax { url: …POST success: (data) => { this.setState(data); } } } Edit Todo editTodo() { $.ajax { url: …PUT success: (data) => { this.setState(data); } } } Get Users getUsers() { $.ajax { url: …GET success: (data) => { this.setState(data); } } } Add User addUser() { $.ajax { url: …POST success: (data) => { this.setState(data); } } } Edit User editUser() { $.ajax { url: …PUT success: (data) => { this.setState(data); } } }
  • 55. Todo App: React with props Data const _props = { todos: [ ‘Todo #1’, ‘Todo #2’ ] } Code render() { return (_.map( this.props.todos, (e) => { return <div>{e}</div> }) ) } Initialize const _root = document.findElementById(‘root’); ReactDOM.render(<TodoApp {..._props} />, _root);
  • 56. Todo App with Flux Data const _props = { todos: [ ‘Todo #1’, ‘Todo #2’ ] } Code render() { return (_.map( this.props.todos, (e) => { return <div>{e}</div> }) ) } Initialize const _root = document.findElementById(‘root’); ReactDOM.render(<TodoApp {..._props} />, _root);
  • 57. Action Creator Trigger <form> <input id=’todo-text’ type=’text’ /> <button onClick=TodoActions.create($(‘#todo-text’).val())>Create</button> </form>
  • 58. Action Creator TodoActions: { create: function(text) { // Take some action, e.g., call REST API AppDispatcher.dispatch({ actionType: TodoConstants.TODO_CREATE, // Basically ‘create’ text: text }); }, …. }
  • 59. Store AppDispatcher.register(function(action) { // action is passed in by Action Creator var event = action.event; switch(action.actionType) { case TodoConstants.TODO_CREATE: // Do whatever, e.g., update local store data or fetch fresh data from server TodoStore.emitChange(); break; …. } } register
  • 60. Store (cont.) var TodoStore = assign({}, EventEmitter.prototype, { // EventEmitter provides emit, on, removeListener, etc. methods addChangeListener: function(callback) { this.on(CHANGE_EVENT, callback); }, removeChangeListener: function(callback) { this.removeListener(CHANGE_EVENT, callback); }, emitChange: function() { this.emit(CHANGE_EVENT); }, ... } register
  • 61. Controller-View // This is where React is used var TodoApp = React.createClass({ componentDidMount: function() { TodoStore.addChangeListener(this._onChange); }, componentWillUnmount: function() { TodoStore.removeChangeListener(this._onChange); }, _onChange: function() { this.setState(TodoStore.getData()); }, ... } register