Building User Interfaceswith React & Flux
Thank You
Burlington JS
John, Matt, Donnie
Who's this guy?
Full-stack dev and team lead working on custom web applications.
Part-time zymurgist, full-time dog parent
*Interested in writing apps in React with ES6?We are hiring front-end and back-end devs!
Things I Like
My Catahoula Leopard Dog Trevor
Not My Favorite Thing
Legacy Code(a.k.a. The stuff I wrote yesterday)
Overview
Why is UI Programming Hard?
What is React?
Components
Props & State
Event Delegation
JSX
App Example
What is Flux?
Flux App Example
Async with Flux
Async Flux App Example
Why is Programming Interactive UI's Hard?
- HTML was designed for documents not user interfaces
- We now use it to build complex user interfaces
- These interfaces are highly interactive
- They have lots of state behind them
- This state changes over time
- State is spread out throughout the code
- State can be changed in many places
- The UI must kept up to date when state changes
- How do separate UI elements communicate or share state
What exactly is state?
Abstract: The data required to render a given user interface.
Concrete: JSON objects.
const state = {
comments: [
{id: 1, text: 'It was great'},
{id: 2, text: 'It was meh'}
],
loading: false
};
What is React?
A library for creating user interfaceswith composable components.
Used by Facebook, Instagram, Netflix, Yahoo!, Khan Academy, Codecademy.
How does React help?
- Clear separation of mutable (state) and immutable (props) state
- Encourages limited mutation of state (props, smart/container vs. dumb components)
- Makes mutation of state explicit (setState)
- Encapsulates how state effects rendering into a single place (render)
- Reduces the need for manual DOM manipulation
Library vs. Framework
React does...
- Declarative nestable views
w/ option handling/defaults
and template rendering
w/ event delegation
- Very little else!
React doesnt...
- HTTP/Network Communication
- Validation
- Models/Persistence
- Routing (react router)
- Services
- So much more!
So React is aTemplating Library?Not really...
Less Like: Rendering HTML (Handlebars, jade, haml).
More Like: Re-usable Components w/ configurable behavior (Angular Directives, jQuery UI Widgets, Web Components)
Example React Component
What will this component render? What behavior will it exhibit?
What is a Component
A component is a small composable unit of a user interface.
A component knows how to output DOM based on state.
Smaller components can be composed together to create more complex user interfaces because they nest like HTML tags.
Kinda Like: Angular directives, jQuery UI Widgets, Web Components
Creating a Component
"If your gonna make a component,you gotta have a render in the class."For many components this is all you need.
Rendering your Component
To render a component, we use React.render tomount our component to a DOM node
PropsData & Options for Components
- Javascript Object
- Accessed via this.props
- Options or data needed by the component to render
- Like jQuery plugin options
- Immutable by convention
- Defaults & Validation included
- Syntax like HTML attributes
- Changes trigger a re-render of component and children
<MyComponent propname="value" >
Event Delegation
- Syntax looks like inline event handlers but uses delegation under the hood
- No automatic context/binding (ES6)
<button onClick={this.handleClick.bind(this)}>GO!</button>
StateA component's local data
- Javascript Object
- Accessed via this.state
- Initialized in the component's constructor
- Private to the component
- Can be mutated by component via this.setState({ key: 'value' })
- Changes trigger a re-render of component and children
Props vs. State...FIGHT!
Props
- Javascript Object
- Changes trigger re-render
- Passed from parent to child
- Immutable by component
- Often not serializable (includes callbacks)
State
- Javascript Object
- Changes trigger re-render
- Initialized by component
- Mutated by the component over time
- Serializable (simple json object)
Inside the Render MethodThe Virtual DOM
- A component's render method does not return a string
- The return value is a javascript object the describes the tree of nested components to render.
Render Method Example
render()
render() {
return <div className="comments"><Comment text="Hello" /></div>
}
Output (simplified)
{
type: 'div',
props: {
className: 'comments',
children: [
{
type: function Comment,
props: {
text: 'Hello'
children: []
}
}
]
}
}
Virtual DOM
- This tree structure is called the Virtual DOM.
- React remembers the virtual dom from component's last render()
- Whenever props/state changes, recursively call render
- Compare the new virtual dom to the old for each component
- Make a batch update at the end of the required DOM changes
Benefits
- No manual DOM manipulation
- Minimizes changes to the DOM
- Easier to reason about what the HTML output will be (Just look at render).
- Components are guaranteed to update whenever props or state change (no dirty tracking)
- Support for multiple render targets (DOM, Reactive Native, ??)
JSXor.. get your filthy HTML out of my Javascript
- JSX is React's templating language for declaratively describing nested trees of components.
- Looks just like HTML (except: className, htmlFor)
- XML-like syntax is highly readable for describing trees
But why put it in the template?
- Component code is highly cohesive/coupled to rendering code (event delegation, convenience accessors)
- Reduce context switching between files
- Component is the logical unit of separation, not technology (HTML vs JS)
Simple Web App Example
JSBin
FluxAn Application Architecture for managing State in React
- Design Pattern* for managing changing/shared state
- Advocates for a uni-directional data flow to trigger state changes and propagate state updates to components
- Defines an application layer where state is stored and changed that lives outside of components
*There are many Flux implementations out there: Alt, Reflux, Fluxible, Redux, McFly, Delorean, Om (ClojureScript) ... seemingly all with pun-y names
Flux Lifecycle in an Oversimplified Nutshell
The user fills out a comment form and clicks the submit button
The form component triggers an AddComment event with data (text, author)
The application layer responsible for handling state changes receives the event and updates its data
... and emits a change event with the new data
The comment list component can listen for the change event and re-render itself/child components via setState
Using Flux Language
The user fills out a comment form and clicks the submit button
The CommentForm component triggers an AddComment action with data (text, author)
The CommentStore receives the AddComment action and updates its state (adds the comment to a list)
... and emits a change event with the new state (new comment list)
The CommentList component listening to the CommentStore receives the new state (comment list) and can re-render itself/child components via setState
Try it again with flow charts
Simple Flux App Example
JSBin
Flux Glossary
-
Components: React Components which trigger Actions based on user input (clicks). They pull their data from and listen to changes in Stores.
-
Actions: Events that needs to trigger a state change (e.g. AddComment, DeleteComment, LikeComment) and carry a data payload from Components to the Stores
-
Stores: Where application state lives. Stores are responsible for keeping application state (the list of comments, ids of comments a user likes) updated by listening to Actions and notifying components of changes by emitting change events
What about AJAX/Async?Depends on the implementation
Async actions which can fail or succeed are generally handled as separate actions: AddComment, AddCommentComplete & AddCommentFailed
The action creator is the name used for a function which a component can call to dispatch an action.
In an action creator for an async action, you would trigger an ajax request and then dispatch the AddCommentComplete or AddCommentFailed actions
depending on the result of the request
Example Async Action w/ Completed/Failed
const commentApi = {
addComment({ newComment }) {
return new Promise(function(resolve, reject) {
if (newComment.text && newComment.author) {
resolve({ newComment: newComment });
} else {
reject({ newComment: newComment, errors: ['Please enter text and an author']});
}
});
}
};
commentActions.addComment.listen(function(newComment) {
commentApi.addComment(newComment)
.then(commentActions.addCommentCompleted)
.catch(commentActions.addCommentFailed);
});
Async Store Example
const commentStore = {
data: { errors: [], loading: false, comments: [] },
init() {
commentActions.addComment.listen(this.addComment);
commentActions.addCommentCompleted.listen(this.addComment);
commentActions.addCommentFailed.listen(this.addComment);
},
addComment() {
this.data.loading = true;
this.trigger(this.data);
},
addCommentCompleted({newComment}) {
this.data.comments = this.data.comments.concat([newComment]);
this.data.loading = false;
this.data.errors = [];
this.trigger(this.data);
},
addCommentCompleted({newComment, errors}) {
this.data.loading = false;
this.data.errors = errors;
this.trigger(this.data);
}
};
Flux App Example w/ ASYNC/AJAX action
JSBin
BONUS: Local Storage for Persistence
JSBin
Questions?
Concerns?
Comments?
Criticisms?
Catechisms?
Cannibalisms?
I just wanted to use all six heading levels for once in my life
Building User Interfaces
with React & Flux