ReactJS, Flux, RelayJS, GraphQL, challenges the way we think & code front-end. This presentation explains what they are, how they work together, and how to get them to work on Rails.
In React/Flux, every time a user interaction triggers a change in a piece of data, the entire set of data for all the pieces of UI flows uni-directionally from the top-level UI to its subcomponents. This strategy helps debugging tremendously since by examining data at a single point we can reason about what when wrong.
RelayJS/GraphQL abstracts the difficult parts of fetching data and caching for UIs into a framework enabling us to simply declare data that we need without having to write AJAX or deal with asynchronous code. This allows us to reduced the server-side to a single API endpoint capable of handling the GraphQL DSL.
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
From Back to Front: Rails To React Family
1. From Back to Front:
Rails to React Family
Khor Soon Hin, @neth_6
2. 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
3. React/Flux/Relay/GraphQL: In A Sentence Each
● React: UI
● Flux: Data Flow
● GraphQL: Data Retrieval
● Relay: Component-Data Co-location
14. 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
25. React: User Interaction (cont.)
jQuery: You need to find element to modify and make modification
26. 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
27. 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
28. React On Rails
● https://github.com/reactjs/react-rails
● app/assets/javascripts/components/xxxxx.js
○ Dump all your React components related to xxxxx
34. React: Summary
Simplify 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
46. Tracing Loops
Difficult:
● Tons of log entries
○ Lots of things to look through
○ Scrolling is laggy
● Cannot just look at snapshot for messy loops
48. MVC Looping the Loop
Explosion 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
49. MVC Simultaneous Loops
Explosion of flows
Error in UI
Tracing is difficult;
seeing two traces
A loop resulting in
multiple other
loops concurrently
56. Side-by-side
● Structured growth (no path explosion):
○ Parallel stores lead to single top view
○ Single-parent cascading views
MVC Flux
React
57. 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
58. With Flux
Error in UI
Only one trace at a
time
● Dispatcher throttles Actions
A loop resulting in
multiple other
loops concurrently
65. 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
66. 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
67. 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
68. 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
69. 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
75. 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
Nested data
query
Client-specified
query
Data in 1
round-trip
76. 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
78. 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
end
end
query {
store(email: "admin@abc.com") {
name,
address
}
}
79. 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 field
end
query {
store(email: "admin@abc.com") {
name,
address
}
}
80. 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 field
end
query {
store(email: "admin@abc.com") {
categories {
name,
products {
name, price, stock
}
}
}
}
81. 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: "admin@abc.com") {
categories {
name,
products {
name, price, stock
}
}
}
}
82. GraphQL: Summary
Simplify:
● 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
93. Relay: Summary
Simplify
● 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
94. How To Get Started Easily?
● Make one piece of UI React
● Make another piece React
● Repeat until SPA
95. Which Should I Use
Partly 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
96. 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?