Crossing the Bridge: Connecting Rails and your Front-end Framework
From Back to Front: Rails To React Family
-
Upload
khor-soonhin -
Category
Software
-
view
509 -
download
0
Transcript of From Back to Front: Rails To React Family
![Page 1: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/1.jpg)
From Back to Front:Rails to React Family
Khor Soon Hin, @neth_6
![Page 2: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/2.jpg)
Outline● React Family: ReactJS/Flux/RelayJS/GraphQL● What makes them interesting?● What are they? How they work together?● How do I get started easily?● Should I use them all?● IMPORTANT: How to get them onto Rails
![Page 3: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/3.jpg)
React/Flux/Relay/GraphQL: In A Sentence Each
● React: UI● Flux: Data Flow● GraphQL: Data Retrieval● Relay: Component-Data Co-location
![Page 4: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/4.jpg)
React/Flux/Relay/GraphQL: Common Goal
Improve software quality given the same development time
![Page 5: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/5.jpg)
React/Flux/Relay/GraphQL: Common Goal
Improve software quality given the same development time
● Easy to understand & debug● Less prone to error
![Page 6: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/6.jpg)
React/Flux/Relay/GraphQL: Common Approach
Simplify abstraction to push common tasks/code organization to pattern/framework
![Page 7: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/7.jpg)
React/Flux/Relay/GraphQL: Common Approach
Simplify abstraction to push common tasks/code organization to pattern/framework
● Easy to understand & debug
![Page 8: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/8.jpg)
React/Flux/Relay/GraphQL: Common Approach
Simplify abstraction to push common tasks/code organization to pattern/framework
● Easy to understand & debug● Less prone to error
![Page 9: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/9.jpg)
React/Flux/Relay/GraphQL: Common Outcome
Functional/Declarative Programming
![Page 10: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/10.jpg)
React: UI
![Page 11: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/11.jpg)
React
● Single-Page Application (SPA)
Courtesy: https://facebook.github.io/react/docs/thinking-in-react.html
![Page 12: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/12.jpg)
React (cont.)
● Single-Page Application (SPA)● Cascading Views
![Page 13: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/13.jpg)
React (cont.)
● Single-Page Application (SPA)● Cascading Views
![Page 14: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/14.jpg)
React (cont.)Abstraction
Each React element knows:
● The data it needs● How to render itself with HTML fragments● The data it passes to its children
![Page 15: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/15.jpg)
React (cont.)
● Single-Page Application (SPA)● Cascading Views
Fetch Data
![Page 16: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/16.jpg)
React (cont.)
● Single-Page Application (SPA)● Cascading Views
![Page 17: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/17.jpg)
React (cont.)
● Single-Page Application (SPA)● Cascading Views
![Page 18: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/18.jpg)
React (cont.)
● Single-Page Application (SPA)● Cascading Views
Uni-directional Flow
![Page 19: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/19.jpg)
React (cont.)
● Single-Page Application (SPA)● Cascading Views
Debug Upwards
![Page 20: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/20.jpg)
React (cont.)
jQuery: You need to find all the pieces of code that modified the UI in error
![Page 21: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/21.jpg)
React: User Interaction
ball
![Page 22: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/22.jpg)
React: User Interaction (cont.)
ball
![Page 23: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/23.jpg)
React: Data Change (cont.)
ball
![Page 24: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/24.jpg)
React: User Interaction (cont.)
ball
![Page 25: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/25.jpg)
React: User Interaction (cont.)
jQuery: You need to find element to modify and make modification
![Page 26: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/26.jpg)
Imperative vs. Functional: Coding● Imperative:
○ Example: jQuery code■ Code is likely in a monolithic Javascript■ Hold element ids for where each piece of data should be shown■ Retrieves element and display data■ Complex model requires customized code:
● Find pieces of data, and update pieces of element
● Functional:○ Example: React code
■ Code is contained within each React element:■ Each React element declares which part of data to pass on to children■ Each React element declares how to render data it receives■ Simplified model reduces code relinquish more to framework:
● Provide data to top view, and cascading views redraws themselves
![Page 27: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/27.jpg)
Functional vs. Imperative: Benefits● Imperative:
○ Complex model requires customized code■ Dig through customized code to understand relationships■ Different pieces of code to initialize UI, and update based on interaction
● Functional:○ Simplified model reduces code relinquish more to framework
■ Relationship and data-flow is top-down■ Same piece of code to initialize, and update UI
![Page 28: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/28.jpg)
React On Rails● https://github.com/reactjs/react-rails● app/assets/javascripts/components/xxxxx.js
○ Dump all your React components related to xxxxx
![Page 29: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/29.jpg)
React: Codevar DATA = [ { category: 'Sporting Goods', products: [ {price: '$49.99', stocked: true, name: 'Football'}, {price: '$9.99', stocked: true, name: 'Baseball'}, {price: '$29.99', stocked: false, name: 'Basketball'}, ], }, { category: 'Electronics', products: [ {price: '$99.99', stocked: true, name: 'iPod Touch'}, {price: '$399.99', stocked: false, name: 'iPhone 5'}, {price: '$199.99', stocked: true, name: 'Nexus 7'}, ], },];
![Page 30: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/30.jpg)
React: Code (cont.)// Javascript required in app/assets/javascripts/application.js
ReactDOM.render( <ProductTable data={DATA} />, document.getElementById('container'));
![Page 31: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/31.jpg)
React: Code (cont.)
// app/assets/javascripts/components/product.jsx
var ProductTable = React.createClass( render: function() { var rows = []; this.props.data.forEach(function(dataElem) { rows.push(<ProductCategoryRow category={dataElem.category} … />); dataElem.products.forEach(function(product) { rows.push(<ProductRow product={product} … />); }); ...
var DATA = [ { category: 'Sporting Goods', products: [ {name: 'Football', ...}, {name: ’Baseball’, ... }, ... ], }, { category: 'Electronics', products: [ {name: 'iPod Touch', ...}, {name: ‘iPhone 6’, …}, ... ], },];
![Page 32: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/32.jpg)
React: Code (cont.)
// app/assets/javascripts/components/product.jsx
var ProductCategoryRow = React.createClass({ render: function() { return (<tr><th>{this.props.category}</th></tr>); }});
![Page 33: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/33.jpg)
React: Code (cont.)// app/assets/javascripts/components/product.jsx
var ProductRow = React.createClass({ render: function() {
return ( <tr> <td>{this.props.product.name}</td> <td>{this.props.product.price}</td> </tr> );
}});
![Page 34: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/34.jpg)
React: SummarySimplify abstraction
● UI○ Shove data for entire UI from the top component○ Each component render itself with data for self○ Each component pass data to child○ To change component, just change data
Framework
● Handle initializing/updating UI with the right pieces of data
How
● Re-drawing all UI pieces efficiently
![Page 35: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/35.jpg)
Flux: Data Flow
![Page 36: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/36.jpg)
React
Courtesy: https://facebook.github.io/react/docs/thinking-in-react.html
![Page 37: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/37.jpg)
MVC
Courtesy: http://fluxxor.com/what-is-flux.html
![Page 38: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/38.jpg)
Multiple Models/Domains
Chat
News
Summary
Friend Requests
![Page 39: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/39.jpg)
MVC ComplexityExplosion of flows
Courtesy: http://fluxxor.com/what-is-flux.html
![Page 40: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/40.jpg)
MVC Complexity
Courtesy: http://fluxxor.com/what-is-flux.html
News
SummaryNews
One model powering 2 views
![Page 41: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/41.jpg)
MVC Complexity
Courtesy: http://fluxxor.com/what-is-flux.html
News
SummaryNews
Friends
One model powering 2 views
Two models powering 1 view
![Page 42: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/42.jpg)
MVC ComplexityExplosion of flows
Error in UI
![Page 43: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/43.jpg)
MVC Complexity (cont.)Explosion of flows
Error in UI
![Page 44: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/44.jpg)
MVC Complexity (cont.)Explosion of flows
Error in UI
![Page 45: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/45.jpg)
MVC Complexity (cont.)Explosion of flows
Error in UI
![Page 46: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/46.jpg)
Tracing LoopsDifficult:
● Tons of log entries○ Lots of things to look through○ Scrolling is laggy
● Cannot just look at snapshot for messy loops
![Page 47: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/47.jpg)
MVC Simple Loops
Error in UI
Tracing (if set correctly) may tell you where loop is
![Page 48: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/48.jpg)
MVC Looping the LoopExplosion of flows
Error in UI
Depending on where you look in the trace, you may think orange or bold loop
A loop resulting in another loop
![Page 49: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/49.jpg)
MVC Simultaneous LoopsExplosion of flows
Error in UI
Tracing is difficult; seeing two traces
A loop resulting in multiple other loops concurrently
![Page 50: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/50.jpg)
Flux
Courtesy: http://fluxxor.com/what-is-flux.html
Trigger ActionAction Done
Action DoneState Update
Structured and self-contained
![Page 51: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/51.jpg)
Flux (cont.)
Courtesy: http://fluxxor.com/what-is-flux.html
Take ActionAction Done
Action DoneState Update
● Throttles one Action at a time● waitsFor()
● Synchronous tasks only● State and logic co-located
![Page 52: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/52.jpg)
Flux (cont.)
Courtesy: http://fluxxor.com/what-is-flux.html
register register
![Page 53: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/53.jpg)
With Flux
Courtesy: http://fluxxor.com/what-is-flux.html
![Page 54: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/54.jpg)
Side-by-side
MVC Flux
![Page 55: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/55.jpg)
Side-by-side● Structured growth (no path explosion):
○ Parallel stores lead to single top view
MVC Flux
![Page 56: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/56.jpg)
Side-by-side● Structured growth (no path explosion):
○ Parallel stores lead to single top view○ Single-parent cascading views
MVC Flux
React
![Page 57: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/57.jpg)
Side-by-side● Structured growth (no path explosion):
○ Parallel stores lead to single top view○ Single-parent cascading views
● Controllers-Models collapsed into Stores to co-locate logic & state
MVC Flux
React
Store
Store
![Page 58: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/58.jpg)
With Flux
Error in UI
Only one trace at a time
● Dispatcher throttles Actions
A loop resulting in multiple other loops concurrently
![Page 59: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/59.jpg)
With Flux
Error in UI
register
register
![Page 60: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/60.jpg)
With Flux
Error in UI
register
register
![Page 61: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/61.jpg)
Todo App
New Todo
Create
Todo #1
Todo #2Created Todo List
![Page 62: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/62.jpg)
Action Creator Trigger<form>
<input id=’todo-text’ type=’text’ />
<button onClick=TodoActions.create($(‘#todo-text’).val())>Create</button>
</form>
![Page 63: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/63.jpg)
Action CreatorTodoActions: { create: function(text) { // Take some action, e.g., call REST API AppDispatcher.dispatch({ actionType: TodoConstants.TODO_CREATE, // Basically ‘create’ text: text }); }, ….}
![Page 64: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/64.jpg)
DispatcherAppDispatcher = require('flux').Dispatcher;
![Page 65: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/65.jpg)
StoreAppDispatcher.register(function(action) { // action is passed in by Action Creatorvar 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
![Page 66: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/66.jpg)
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
![Page 67: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/67.jpg)
Controller-View// This is where React is usedvar TodoApp = React.createClass({ componentDidMount: function() { TodoStore.addChangeListener(this._onChange); }, componentWillUnmount: function() { TodoStore.removeChangeListener(this._onChange); }, _onChange: function() { this.setState(TodoStore.getData()); }, ...}
register
![Page 68: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/68.jpg)
Flux: More Pattern than Framework● Many implementations● Flux:
○ By Facebook
● Redux:○ Not pure Flux per se, but embraces its spirit○ Server-side rendering built-in○ Growing super-fast
● Alt:○ Pure Flux compliant○ Well-documented, great community○ Server-side rendering built-in
![Page 69: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/69.jpg)
Flux Documentation Quirks● Uses native dispatcher, not the official Facebook dispatcher
○ Use official Facebook dispatcher
● Does not use Flux-Utils○ Use Flux-Utils to create Stores without code duplication
Rails with pure Flux: https://medium.com/@khor/back-to-front-rails-to-facebook-s-flux-ae815f81b16c
![Page 70: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/70.jpg)
GraphQL: Data Retrieval
![Page 71: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/71.jpg)
GraphQL
I speak GraphQL
API Endpoint
![Page 73: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/73.jpg)
GraphQL (cont.)
API Endpoint
query { store(email: "[email protected]") { name, address }}
store(email: “[email protected]”) { name: ‘Hello Shop’, address: ‘1-3-1 Aoyama’}
![Page 74: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/74.jpg)
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 }, … }, ... ]}
From React example
![Page 75: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/75.jpg)
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
Nested data query
Client-specified query
Data in 1 round-trip
![Page 76: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/76.jpg)
GraphQL (cont.)REST API:
● 3 endpoints:○ Endpoint for Store○ Endpoint for Category○ Endpoint for Product
● Server-controlled query○ Query for store returns email, name, address, etc. whether you want it or not
● Multiple round-trips vs. impure-REST/endpoint proliferation○ Get Store, get each Category, get each Product in each Category○ Lumping them together creates view-specific endpoints
![Page 77: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/77.jpg)
GraphQL Enabled
https://github.com/rmosolgo/graphql-ruby
I speak GraphQL
API Endpoint
![Page 78: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/78.jpg)
GraphQL: Schema # app/graph/types/query_type.rb
field :store do type StoreType # Shape of this type argument :email, !types.String, "Email of Store owner" ... # Retrieve data resolve -> (obj, args, ctx) do Store.find_by_email(args[:email]) # ActiveRecord stuff endend
query { store(email: "[email protected]") { name, address }}
![Page 79: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/79.jpg)
GraphQL: Schema (cont.) # app/graph/types/store_type.rb
StoreType = GraphQL::ObjectType.define do name "Store" description "Store Data" … field :name, !types.String, "Store name" # From ActiveRecord field field :address, !types.String, "Store address" # From ActiveRecord field field :categories, !types[CategoryType], “Category list” # From ActiveRecord fieldend
query { store(email: "[email protected]") { name, address }}
![Page 80: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/80.jpg)
GraphQL: Schema (cont.) # app/graph/types/store_type.rb
StoreType = GraphQL::ObjectType.define do name "Store" description "Store Data" … field :name, !types.String, "Store name" # From ActiveRecord field field :address, !types.String, "Store address" # From ActiveRecord field field :categories, !types[CategoryType], “Category list” # From ActiveRecord fieldend
query { store(email: "[email protected]") { categories { name, products { name, price, stock } } }}
![Page 81: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/81.jpg)
GraphQL: Schema (cont.) # app/graph/types/category_type.rb
CategoryType = GraphQL::ObjectType.define do name "Category" description "Category Data" … field :name, !types.String, "Category name" # From ActiveRecord field field :products, !types[ProductType], “Product list” # From ActiveRecord field ...end
query { store(email: "[email protected]") { categories { name, products { name, price, stock } } }}
![Page 82: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/82.jpg)
GraphQL: SummarySimplify:
● Efficient request for data that you need from server endpoint
Framework
● A single API endpoint to respond to query● Query language that enables client to specify data required, ala SQL● No over-fetch● Request all data in a single query
![Page 83: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/83.jpg)
Relay: Component-Data Co-location
![Page 84: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/84.jpg)
Relay: Declare Data
![Page 85: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/85.jpg)
Relay: Declare Data
![Page 86: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/86.jpg)
React: Recap (cont.)Fetch Data (AJAX)
![Page 87: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/87.jpg)
React: Recap (cont.)
![Page 88: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/88.jpg)
React: Recap (cont.)
![Page 89: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/89.jpg)
Relay: GraphQL Fetch Relay/GraphQL
![Page 90: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/90.jpg)
Relay: Why Data Declaration? Pass All Data
![Page 91: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/91.jpg)
GraphQL/Relay Enabled
gem ‘graphql-ruby’
I speak GraphQL/Relay
API Endpoint
gem ‘graphql-relay-ruby’Relay Layer
‘react-relay’
![Page 92: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/92.jpg)
Relay/GraphQL on Rails
Relay/GraphQL on Rails: https://medium.com/@khor/relay-facebook-on-rails-8b4af2057152
![Page 93: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/93.jpg)
Relay: SummarySimplify
● Data fetching related stuff○ Show ‘Loading….’○ Data re-fetching○ Caching
■ Figuring out batching, reading/writing caching, fetching only missing pieces■ NOTE: Caching is NOT new but handling caching for hierarchical data is rather new
○ Managing errors, retry failed requests○ Optimistic updates○ Pagination
Framework
● Use GraphQL to fetch all required data declaratively● Handle all the above
![Page 94: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/94.jpg)
How To Get Started Easily?● Make one piece of UI React● Make another piece React● Repeat until SPA
![Page 95: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/95.jpg)
Which Should I UsePartly from: https://facebook.github.io/react/blog/2015/02/20/introducing-relay-and-graphql.html
Flux Relay/GraphQL
Multiple stores (one per domain) Single store (GraphQL server)
Explicit subscription Implied subscription based on data required
Actions (possibly with AJAX) Mutations (query with changes)
REST API pros, and cons Efficient data handling (batching, caching, no over-fetching, etc.)
More customized coding Generic framework for data access, updates, etc.
Prefer imperative debugging Love magic, abstractions, and puzzle debugging
![Page 96: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/96.jpg)
Other Stuff● React
○ Must all user-interaction go to top? Must top do all data manipulation?
● GraphQL○ Can I just use GraphQL? Do I need Relay?
● Relay○ How to modify Model without AJAX?○ There is no gem?
![Page 97: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/97.jpg)
Thank You!
![Page 98: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/98.jpg)
Primary ResourcesThinking in React: https://facebook.github.io/react/docs/thinking-in-react.html
Flux Best Practices: https://facebook.github.io/flux/docs/flux-utils.html
Nested Relay Components: https://facebook.github.io/react/blog/2015/03/19/building-the-facebook-news-feed-with-relay.html
![Page 99: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/99.jpg)
Practical ResourcesRails with pure Flux: https://medium.com/@khor/back-to-front-rails-to-facebook-s-flux-ae815f81b16c
Relay/GraphQL on Rails: https://medium.com/@khor/relay-facebook-on-rails-8b4af2057152
Relay/GraphQL Rails Starter Kit: https://github.com/nethsix/relay-on-rails
![Page 100: From Back to Front: Rails To React Family](https://reader036.fdocuments.us/reader036/viewer/2022092622/587759a21a28ab4e4f8b505b/html5/thumbnails/100.jpg)
ReferencesFlux Comparisons:
● https://medium.com/social-tables-tech/we-compared-13-top-flux-implementations-you-won-t-believe-who-came-out-on-top-1063db32fe73
● http://jamesknelson.com/which-flux-implementation-should-i-use-with-react/
Introduction to GraphQL: http://facebook.github.io/react/blog/2015/02/20/introducing-relay-and-graphql.html
Thinking In GraphQL: https://facebook.github.io/relay/docs/thinking-in-graphql.html
Thinking In Relay: https://facebook.github.io/relay/docs/thinking-in-relay.html