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)

PPTX
Getting started with react &amp; redux
PPTX
Relay: Seamless Syncing for React (VanJS)
PDF
React, GraphQL и Relay - вполне себе нормальный компонентный подход (nodkz)
PDF
React JS and why it's awesome
PPTX
2.React tttttttttttttttttttttttttttttttt
PPTX
PPSX
React introduction
PPTX
Reactjs
PDF
貴圈真亂 React生態圈
PPTX
React workshop
PDF
Boosting Data Fetching in Turkish Apps with React Native and GraphQL
PDF
React native meetup 2019
PDF
ReactJS presentation
PPTX
reactJS
PDF
An Intense Overview of the React Ecosystem
PDF
An Overview of the React Ecosystem
PPTX
React Workshop: Core concepts of react
PDF
ReactJS - A quick introduction to Awesomeness
PDF
theory-slides-vueh3urh4ur4ur4r44oirj4riu4ri
PDF
GraphQL With Relay Part Deux
Getting started with react &amp; redux
Relay: Seamless Syncing for React (VanJS)
React, GraphQL и Relay - вполне себе нормальный компонентный подход (nodkz)
React JS and why it's awesome
2.React tttttttttttttttttttttttttttttttt
React introduction
Reactjs
貴圈真亂 React生態圈
React workshop
Boosting Data Fetching in Turkish Apps with React Native and GraphQL
React native meetup 2019
ReactJS presentation
reactJS
An Intense Overview of the React Ecosystem
An Overview of the React Ecosystem
React Workshop: Core concepts of react
ReactJS - A quick introduction to Awesomeness
theory-slides-vueh3urh4ur4ur4r44oirj4riu4ri
GraphQL With Relay Part Deux
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
Advanced IT Governance
PDF
GamePlan Trading System Review: Professional Trader's Honest Take
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
How Onsite IT Support Drives Business Efficiency, Security, and Growth.pdf
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
AI And Its Effect On The Evolving IT Sector In Australia - Elevate
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PPT
Teaching material agriculture food technology
PDF
CIFDAQ's Market Wrap: Ethereum Leads, Bitcoin Lags, Institutions Shift
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
Big Data Technologies - Introduction.pptx
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Electronic commerce courselecture one. Pdf
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
Advanced IT Governance
GamePlan Trading System Review: Professional Trader's Honest Take
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
How Onsite IT Support Drives Business Efficiency, Security, and Growth.pdf
Dropbox Q2 2025 Financial Results & Investor Presentation
AI And Its Effect On The Evolving IT Sector In Australia - Elevate
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Teaching material agriculture food technology
CIFDAQ's Market Wrap: Ethereum Leads, Bitcoin Lags, Institutions Shift
20250228 LYD VKU AI Blended-Learning.pptx
Big Data Technologies - Introduction.pptx
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Electronic commerce courselecture one. Pdf
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Review of recent advances in non-invasive hemoglobin estimation
Reach Out and Touch Someone: Haptics and Empathic Computing
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Chapter 3 Spatial Domain Image Processing.pdf
Spectral efficient network and resource selection model in 5G networks

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: “[email protected]”) { 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: "[email protected]") { name, address } }
  • 8. GraphQL (cont.) API Endpoint query { store(email: "[email protected]") { name, address } } store(email: “[email protected]”) { 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: "[email protected]") { 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: "[email protected]") { 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: “[email protected]”) { 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: “[email protected]”) { 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: “[email protected]”) { 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: “[email protected]”) { 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