React From Scratch - Software Design & Development...
Transcript of React From Scratch - Software Design & Development...
@housecor | bitnative.com
Cory House
React From Scratch
github.com/coryhouse/fluent2016Go here and get setup!
Finished demo: github.com/coryhouse/fluent2016complete
Plan to code along with me?
Focus: Code or concepts?
Atom or Webstorm?
Light or dark theme?
Breaks?
Questions:
To code along with me:
git clone https://github.com/coryhouse/fluent2016.git
Start github.com/coryhouse/fluent2016
Finish github.com/coryhouse/fluent2016complete
Code snippets bit.ly/fluent2016reactplan
A World of Components
They call it React for a reason.
JSX
Virtual DOM
Isomorphic Rendering
Unidirectional Flows
Innovation
Try to keep an open mind.
HTML should be a projection of app state, not a source of truth.
JavaScript and HTML belong in the same file.
Unidirectional flow. No two-way binding.
Inline styles can be good.
All Variables Should be Global.
Battle Proven
Morning:
React
Afternoon:
React exercises
Development environment
Testing
Redux
Here’s the Plan
Environment Setup
You don’t need all this tech to work with
React and Flux.
Don’t Let This Scare You…
Just type “npm start”, get all this…
▪ Compile React JSX
▪ Lint JSX and JS via ESLint
▪ Bundle JS and CSS files
▪ Migrate the built app to the dist folder
▪ Run a dev webserver
▪ Open the browser at your dev URL
▪ Reload the browser upon save
Our Goal
Core Technologies
Server-side JavaScript Components
Unidirectional data
flows
Task runner
Node packages in the browser
Routing
Server-side JS
Uses the V8 Engine
Includes npm package manager
Node
.NET
Ruby
Java
Python
PHP
The Web
Node
npm: Node’s Package Manager
CommonJS Pattern
//1. Get reference to dependencyvar dependency = require('/path/to/file');
//2. Declare modulevar MyModule = {//code here…
}
//3. Expose to othersmodule.exports = MyModule;
Use Node modules in the browser
Bundle dependencies
Webpack
Component Library
Simple composition
Utilizes virtual DOM
Can render on client and server
React
Uni-directional data flows
Redux
Run tasks
Rich plugin ecosystem
Stream-based
npm Scripts
Approved June 2015
Widespread browser support
Can transpile to ES5 via Babel
ES2015 (ES6)
Approved in 2009
The JS you already know
Excellent browser support
ES5
What about ES2015?
What about ES2015?
Node & npm Packages
React Components
Redux Data flows
Webpack Bundler
Npm Scripts Automationandbuilds
Wrap Up
JSX
This baby is clearly
adorable.
Imagine an ugly baby here.
“HTML” in JavaScript
Compiles to JavaScript
Differences: className, htmlFor
Optional
JSX
React.createElement("h1", {color: "red"}, "Heading here")
<h1 color="red">Heading here</h1>
JSX Compiles to JS
What about separation of concerns?
“JS” in HTML
<div ng-repeat="user in users">
{{#each user in users}}
data-bind="foreach: users">
“HTML” in JS
{users.map(createUserRow)}
Must stay in sync.
No explicit interface!
Separating intertwined concerns hinders debugging
Compile-time error checking FTW!
M V C
M V C
JSX Friendly Editors
Virtual DOM
Updating the DOM is expensive
Why Virtual DOM?
Compare DOM’s current state to
desired new state.
Update the DOM in the most
efficient way.
With Virtual DOM
Blindly update DOM using new
state.
Without Virtual DOM
The Virtual DOM
Removing a Row…
Redraws entire table Removes the row
Hard to argue with the results…
Performance
Performance
shouldComponentUpdate
PureRenderMixin + immutability
Performance: Go Even Faster
Meh, my app is fast enough.
Half second delay -> 20% drop in traffic.
Delayed in increments of 100
milliseconds
Even very small delays resulted in
substantial drops in revenue.
Synthetic Events
Isomorphic Support
React Native
Hot Reloading
Virtual DOM: More Than Performance
Let’s code our first components!
Time to start coding!
▪ Create our first React components
▪ Setup custom routing
▪ Create centralized layout
▪ Discuss naming conventions
Here’s the Plan
chatApp.jsChatApp.jsxChatApp.react.js
Naming React Files
.js .jsx
All IDEs will at least highlight JS
Default application/icon
Require statements assume JS
Doesn’t distinguish JSX from JS
Lies about contents
May confuse IDE highlighting
Some IDEs won’t highlight any syntax
No default application/icon
Must use .jsx extension to require
Distinguishes JS from JSX
Clarifies content
IDE knows to parse & color as JSX
Which Extension?
React Component Approaches
▪ React component creation approaches
▪ Container vs Presentational Components
Here’s the Plan
Four+ Ways to Create React Components?!
▪ ES5 createClass
▪ ES6 class
▪ ES5 stateless function
▪ ES6 stateless function
▪ Many more…
Ways to Create Components
var HelloWorld = React.createClass({
render: function () {
return (
<h1>Hello World</h1>
);
}
});
ES5 Class Component
class HelloWorld extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<h1>Hello World</h1>
);
}
}
ES6 Class Component
This slide is with
animations
▪ No autobind
▪ PropTypes declared separately
▪ Default props declared separately
▪ Set initial state in constructor
React in ES6
var HelloWorld = function(props) {
return (
<h1>Hello World</h1>
);
});
ES5 Stateless Functional Component
const HelloWorld = (props) => {
return (
<h1>Hello World</h1>
);
});
ES6 Stateless Functional Component
This slide is with
animations
▪ No class needed
▪ Avoid `this` keyword
▪ Enforced best practices
▪ High signal-to-noise ratio
▪ Enhanced code completion / intellisense
▪ Bloated components are obvious
▪ Easy to understand
▪ Easy to test
▪ Performance
Stateless Functional Components: 9 Benefits
Use stateless functional components when possible.
▪ Class Component
State
Refs
Lifecycle methods
Child functions (for performance)
▪ Stateless Components
Everywhere else ☺
When Should I Use Each?
This slide is with
animations
▪ Object.create
▪ Mixins
▪ Parasitic Components
▪ StampIt
More info: bit.ly/react-define-component
Other Ways to Create Components
Container vs Presentation Components
▪ Container
Little to no markup
Pass data and actions down
Knows about Redux
Often stateful
▪ Presentation
Nearly all markup
Receive data and actions via props
Doesn’t know about Redux
Typically functional components
Most components
Container
Smart
Stateful
Controller View
Presentational
Dumb
Stateless
View
Alternative Jargon
”When you notice that some components
don’t use props they receive but merely
forward them down…it’s a good time to
introduce some container components.”
Dan Abramov
This bullet list is with
animations
▪ ES5 createClass
▪ ES6 Class
▪ ES5 Stateless Function
▪ ES6 Stateless Function
▪ Many more!
▪ Container vs Presentation Components
▪ Next up: Let’s start building!
Wrap up
React Lifecycle
▪ Props
▪ State
▪ Dynamic child components
▪ Lifecycle functions
▪ Demo time!
- Mock API
- Dynamic components
Here’s the Plan
Props – Look like HTML attributes, but immutable
this.props.username
State – Holds mutable state
this.state.username
Props and State
▪ getInitialState
Initial State
▪ getDefaultProps
Default Prop Values
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
Lifecycle Methods
When
Before initial render, both client and server
Why
Good spot to set initial state
componentWillMount
When
After render
Why
Access DOM, integrate with frameworks, set timers, AJAX requests
componentDidMount
When
When receiving new props. Not called on initial render.
Why
Set state before a render.
componentWillReceiveProps
When
Before render when new props or state are being received.
Not called on initial render.
Why
Performance. Return false to void unnecessary re-renders.
shouldComponentUpdate
When
Immediately before rendering when new props or state are being received.
Not called on initial render.
Why
Prepare for an update
componentWillUpdate
When
After component's updates are flushed to the DOM.
Not called for the initial render.
Why
Work with the DOM after an update
componentDidUpdate
When
Immediately before component is removed from the DOM
Why
Cleanup
componentWillUnmount
Add a key to dynamic child elements
<tr key={author.id}>
Keys for Dynamic Children
Props Pass data to child components
State Data in controller view
Lifecycle Handle bootstrapping and third party integrations
Summary
Composing Components
Our focus: Composition
Controller views
Prop validation via PropTypes
Mixins
Here’s the Plan
Composition
Interacts with storesSets props on
childrenTop level component
Controller Views
Controller Views
propTypes: {
author: React.PropTypes.object.isRequired,
onSave: React.PropTypes.func.isRequired,
validate: React.PropTypes.func.isRequired,
errors: React.PropTypes.object,
hasErrors: React.PropTypes.func.isRequired,
},
Prop Validation
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
Prop Validation
Minified version is for production.
Development vs Production Mode
Declare expected property types
Prop Validation
Controller Views “Smart” components that pass data down via props
PropTypes Validate props
Summary
@housecor bitnative.com
Cory House
Testing and Continuous Integration
This bullet list is with
animations
▪ JavaScript testing styles
▪ 6 key testing decisions
▪ Configure testing and write test
▪ Continuous integration
Here’s the Plan
This slide is with
animations
JavaScript Testing Styles
Style Focus
Unit Single function or module
Integration Interactions between modules
UI Automate interactions with UI
3▪ Helper Libraries
6▪ Where to place tests
1Framework
2▪ Assertion Library
4▪ Where to run tests
5▪ When to run tests
Unit Testing Decisions
Decision #1:Testing Framework
▪ Tape
▪ AVA
Mocha ▪ Jasmine
▪ QUnit ▪ Jest
Testing Frameworks
It’s Like Choosing a Gym
The important part is showing up.
Right Answer Wrong Answer
Any of these!
Woah, decision fatigue!
I’ll just keep coding
and praying.
Decision #2:Assertion Library
This slide is with
animations
▪ Declare what you expect
What’s An Assertion?
expect(2+2).to.equal(4)
assert(2+2).equals(4)
Assertion Libraries
Decision #3:Helper Library
This slide is with
animations
▪ Simulate the browser’s DOM
▪ Run DOM-related tests without a browser
JSDOM
This slide is with
animations
▪ jQuery for the server
▪ Query virtual DOM using jQuery selectors
Cheerio
Decision #4:Where to Run Tests
This slide is with
animations
▪ Browser
- Karma, Testem
▪ Headless Browser
- PhantomJS
▪ In-memory DOM
- JSDOM
Where to Run Tests
Decision #5:Where do test files belong?
Centralized
Less “noise” in src folder
Deployment confusion
Inertia
Alongside
Easy imports
Clear visibility
Convenient to open
No recreating folder structure
Easy file moves
Where Do Test Files Belong?
// file.test.js
import file from '../../src/long/path'
// file.test.js
import file from './file'
Path to file under test is always ./filename ☺
Naming Test Files
Decision #6:When should tests run?
This slide is with
animations
▪ Rapid feedback
▪ Facilitates TDD
▪ Automatic = Low friction
▪ Increases test visibility
Unit Tests Should Run When You Hit Save
But Cory, my tests are
too slow!
- You, my viewer with slow tests
▪ Unit Tests
Test a small unit
Often single function
Fast
Run upon save
▪ Integration Tests
Test multiple units
Often involves clicking and waiting
Slow
Often run on demand, or in QA
3▪ Helper Libraries
6▪ Where to place tests
1Framework
2▪ Assertion Library
4▪ Where to run tests
5▪ When to run tests
Here’s the Plan
ChaiMocha JSDOM
Node Alongside Upon save
Demo
This bullet list is with
animations
▪ Configure automated testing
Continuous Integration
Weird.
Works on my
machine.
- Developer without a CI server
This slide is with
animations
▪ Forgot to commit new file
▪ Forgot to update package.json
▪ Commit doesn’t run cross-platform
▪ Node version conflicts
▪ Bad merge
▪ Didn’t run tests
▪ Catch mistakes quickly
Why CI?
This slide is with
animations
▪ Run Automated build
▪ Run your tests
▪ Check code coverage
▪ Automate deployment
What Does a CI Server Do?
Travis
Continuous Integration
Appveyor Jenkins
Demo
This bullet list is with
animations
▪ Set up Continuous Integration
This bullet list is with
animations▪ Testing frameworks
- Mocha, Jasmine, AVA, Tape, Jest…
▪ Assertion libraries
- Chai, Expect
▪ Helper libraries
- JSDOM, Cheerio
▪ Where to run tests
- Browser, Headless, In memory
▪ Where to place tests, and when to run
▪ Continuous Integration
- Travis CI, Appveyor, Jenkins
▪ Next up: HTTP and Mock APIs
Wrap Up
Demo
This bullet list is with
animations
▪ Production build process
- Lint and runs tests
- Bundle and minify JS and CSS
- Generate JS and CSS sourcemaps
- Exclude dev-specific concerns
- Build React in production mode
- Open prod build in browser
Production Builds Matter
▪ Dev
build▪ 4.8MB
▪ Prod build▪ Essentials
121K 64K!
Drop babel-polyfill, toastr, jQuery, Bootstrap
Flux
A pattern
Centralized dispatcher
Unidrectional data flows
What is Flux?
They call it Flux for a reason too.
Facebook’s Flux
Alt
Reflux
Flummox
Marty
Fluxxor
Delorean
Redux
NuclearJS
Fluxible
Flux Implementations
Good Luck Debugging This
Two-way binding
Two-way Binding vs Unidirectional
React
View
Action
Dispatcher
Store
Unidrectional
View
Viewmodel
Flux: 3 Parts
Delete User
Notify everyone who cares
Hold app state and logic
React
View
Action
Dispatcher
Store
Encapsulate events
Triggered by user interactions and
server
Passed to dispatcher
Actions
React
View
Action
Dispatcher
Store
Actions
React
View
Action
Dispatcher
Store
Payload has type and data
{
type: USER_SAVED
data: {
firstName: ‘Cory’,
lastName: ‘House;
}
}
Central Hub – There’s only one
Holds list of callbacks
Broadcasts payload to registered
callbacks
Sends actions to stores
Dispatcher
React
View
Action
Dispatcher
Store
Keeps things organized
Provides high level view of what the app actually does
Constants
Holds app state, logic, data retrieval
Not a model - Contains models.
One, or many
Registers callbacks with dispatcher
Uses Node’s EventEmitter
Store
React
View
Action
Dispatcher
Store
Every store has these common traits (aka interface)
1. Extend EventEmitter
2. addChangeListener and removeChangeListener
3. emitChange
The Structure of a Store
Dispatcher
Payload
Product
StoreUser Store
Address
Store
{
type: USER_SAVED
data: {
firstName: ‘Cory’,
lastName: ‘House;
}
}
As an application grows, the dispatcher
becomes more vital, as it can be used to
manage dependencies between the stores
by invoking the registered callbacks in a
specific order. Stores can declaratively
wait for other stores to finish updating,
and then update themselves accordingly.Flux Documentation
I usually view ActionCreators as something that is used
for writes to the server. For example, the user added a
new message by clicking the Send button, so the
responsible view calls into ActionCreator.
On the other hand, if a store needs to fetch data from
the server, then that doesn't have to use an
ActionCreator. Instead, the store can directly hit an
endpoint to load its data, and then direct the response
through the dispatcher.Jing Chen, Facebook
Top level component
Interacts with Stores
Holds data in state
Sends data to children as props
Controller Views
React
View
Action
Dispatcher
Store
React View
Action
Dispatcher
Store
Web API
Send
Action
Payload
Send
Action
Payload
Updates storage and
fires change event
Payload sent to dispatcher
Checks for registered callbacks
Sends payload to all registered
callbacks
Receives payload
Store updates and emits change event
Payload:
{
type: USER_SAVED
data: {
firstName: 'Cory',
lastName: 'House';
}
}
User clicked “Save User” button…
Receives change event and re-renders
React Hey CourseAction, someone clicked this “Save Course” button.
Action Thanks React! I registered an action creator with the dispatcher, so the dispatcher should take care of notifying all the stores that care.
Dispatcher Let me see who cares about a course being saved. Ah! Looks like the CourseStore has registered a callback with me, so I’ll let her know.
Store Hi dispatcher! Thanks for the update! I’ll update my data with the payload you sent. Then I’ll emit an event for the React components that care.
React Ooo! Shiny new data from the store! I’ll update the UI to reflect this!
A Chat With Flux
Flux API
register(function callback) – “Hey dispatcher, run me when actions happen. -
Store”
unregister(string id) – “Hey dispatcher, stop worrying about this action. - Store”
waitFor(array<string> ids) – “Update this store first. – Store”
dispatch(object payload) - “Hey dispatcher, tell the stores about this action. -
Action”
isDispatching() – “I’m busy dispatching callbacks right now.”
Flux is a pattern for unidirectional data flows
Actions encapsulate events
Dispatcher is a central hub that holds callbacks
Stores holds app state
Many implementations
Summary
React
View
Action
Dispatcher
Store
Let’s code Flux!
Why Redux?
A Silly Number of Flux Flavors
Flux Many more…Redux
Two Most Popular Flavors
Flux Redux
React
Flux
Redux
Faceboo
k Hires
Redux
Creator
2013
2014
2015
2016
This slide is with
animations
▪ One Store
▪ Reduced Boilerplate
▪ Isomorphic/Universal Friendly
▪ Immutable Store
▪ Hot Reloading
▪ Time-travel debugging
▪ Small
Why Redux?
Boilerplate Magic
Flux Redux
@housecor reactjsconsulting.com
Cory House
Intro to Redux
This bullet list is with
animations
▪ Do I need Redux?
▪ 3 Principles
▪ Flux vs Redux
▪ Redux Flow
Here’s The Plan
Do I need Redux?
Vanilla JS
Simple Complex
jQuery React React + Redux
No setup Significant setup
This slide is with
animations
▪ Complex data flows
▪ Inter-component communication
▪ Non-heirarchical data
▪ Many actions
▪ Same data used in multiple places
When Do I Need Redux?
“…If you aren’t sure if you need it,
you don’t need it.”
Pete Hunt on Flux and Redux
Store
Action: Create User
One immutable store
Redux: 3 Principles
Actions trigger changes Reducers update state
Flux vs Redux
Data down.Actions up.
Unidirectional Flow
Flux and Redux: Similarities
Actions Stores
Reducers
Redux: New Concepts
Containers Immutability
▪ Flux ▪ Redux
Flux vs Redux
React
Action
Dispatcher
Store
React
Action
ReducersStore
▪ Flux
Stores contain state and change logic
▪ Redux
Store and change logic are separate
▪ Flux
Stores contain state and change logic
Multiple stores
▪ Redux
Store and change logic are separate
One store
▪ Flux
Stores contain state and change logic
Multiple stores
Flat and disconnected stores
▪ Redux
Store and change logic are separate
One store
Single store with hierarchical reducers
▪ Flux
Stores contain state and change logic
Multiple stores
Flat and disconnected stores
Singleton dispatcher
▪ Redux
Store and change logic are separate
One store
Single store with hierarchical reducers
No dispatcher
▪ Flux
Stores contain state and change logic
Multiple stores
Flat and disconnected stores
Singleton dispatcher
React components subscribe to stores
▪ Redux
Store and change logic are separate
One store
Single store with hierarchical reducers
No dispatcher
Container components utilize connect
▪ Flux
Stores contain state and change logic
Multiple stores
Flat and disconnected stores
Singleton dispatcher
React components subscribe to stores
State is mutated
▪ Redux
Store and change logic are separate
One store
Single store with hierarchical reducers
No dispatcher
Container components utilize connect
State is immutable
Redux Flow
Redux Flow
function appReducer(state = defaultState, action) {
switch(action.type) {
case RATE_COURSE:
//return new state
}
}
{ type: RATE_COURSE, rating: 5 }
Notified via React-ReduxReact
Action
ReducersStore
This bullet list is with
animations
▪ If you need Redux, you’ll know it.
▪ 3 Principles
- Immutable Store
- Actions trigger changes
- Reducers return updated state
▪ Flux vs Redux
▪ Unidirectional Redux Flow
▪ Next up: Actions, stores, and reducers
Summary
@housecor reactjsconsulting.com
Cory House
Actions, Store, and Reducers
This bullet list is with
animations
▪ Actions
▪ Store
▪ Immutability
▪ Reducers
Here’s The Plan
rateCourse(rating) {
return { type: RATE_COURSE, rating: rating }
}
Action Creators
Action
Action Creator
This slide is with
animations
▪ let store = createStore(reducer);
Creating Redux Store
This slide is with
animations
▪ store.dispatch(action)
▪ store.subscribe(listener)
▪ store.getState()
▪ replaceReducer(nextReducer)
Redux Store
Immutability
Immutability:To change state, return a new object.
▪ Immutable already! ☺
Number
String,
Boolean,
Undefined,
Null
▪ Mutable
Objects
Arrays
Functions
What’s Mutable in JS?
state = {
name: 'Cory House'
role: 'author'
}
state.role = 'admin';
return state;
Current state
Traditional App - Mutating state
state = {
name: 'Cory House'
role: 'author'
}
return state = {
name: 'Cory House'
role: 'admin'
}
Current state
Returning new object. Not mutating state! ☺
Signature
Object.assign(target, ...sources)
Example
Object.assign({}, state, {role: 'admin'});
Copy
▪ Flux
State is mutated
▪ Redux
State is immutable
▪ Clarity
▪ Performance
▪ Awesome Sauce
Why Immutability?
“Huh, who changed that state?”
Immutability = Clarity
The reducer, stupid!
▪ Clarity
▪ Performance
▪ Awesome sauce
Why Immutability?
state = {
name: 'Cory House'
role: 'author'
city: 'Kansas City'
state: 'Kansas'
country: 'USA'
isFunny: 'Rarely'
smellsFunny: ’Often'
...
}
Immutability = Performance
Has this changed?
if (prevStoreState !== storeState) ...
▪ Clarity
▪ Performance
▪ Awesome Sauce
Why Immutability?
(Amazing debugging)
▪ Time-travel debugging
▪ Undo/Redo
▪ Turn off individual actions
▪ Play interactions back
Immutability = AWESOME SAUCE!
Handling Immutability
ES6
▪ Object.assign
▪ Spread operator
ES5
▪ Lodash merge
▪ Lodash extend
▪ Object-assign
Libraries
• react-addons-update
• Immutable.js
Handling Immutable State
JavaScript's primitives are immutable.
Trust
How Do I Enforce Immutability?
redux-immutable-state-
invariant
Immutable.js
Reducers
What is a Reducer?
▪ function myReducer(state, action) {
▪ // Return new state based on action passed
▪ }
This slide is with
animations
(state, action) => state
What is a Reducer?
▪ function myReducer(state, action) {
▪ // Return new state based on action passed
▪ }
So approachable.
So simple.
So tasty.
What is a Reducer?
▪ function myReducer(state, action) {
switch (action.type) {
case ‘INCREMENT_COUNTER’:
state.counter++;
return state;
}
▪ }
Uh oh, can’t do this!
What is a Reducer?
▪ function myReducer(state, action) {
switch (action.type) {
case ‘INCREMENT_COUNTER’:
return (Object.assign(
{},
state,
{counter: state.counter + 1}
);
}
▪ }
Reducers must be pure.
▪ Mutate arguments
▪ Perform side effects
▪ Call non-pure functions
Forbidden in Reducers
1 Store. Multiple Reducers.
New State
authors
loadStatu
s
courses
All Reducers Are Called on Each Dispatch{ type: DELETE_COURSE, 1 }
Reducer = “Slice” of State
authors
courses
loadingStatus
Store
“Write independent small reducer functions
that are each responsible for updates to a
specific slice of state. We call this pattern
“reducer composition”. A given action could
be handled by all, some, or none of them.”Redux FAQ
This bullet list is with
animations
▪ Actions
- Represent user intent
- Must have a type
▪ Store
- dispatch, subscribe, getState…
▪ Immutability
- Just return a new copy
▪ Reducers
- Must be pure
- Multiple per app
- Slice of state
Summary
Next up: Connecting React to Redux
@housecor reactjsconsulting.com
Cory House
Connecting React to Redux
This bullet list is with
animations
▪ Container vs Presentation Components
▪ React-Redux
- Provider
- Connect
▪ A Chat with Redux
Here’s The Plan
▪ Container
Focus on how things work
Aware of Redux
Subscribe to Redux State
Dispatch Redux actions
Generated by react-redux
▪ Presentational
Focus on how things look
Unaware of Redux
Read data from props
Invoke callbacks on props
Written by hand
Two Component Types
Connecting React to Redux
React
Action
ReducersStore
react-redux
Connect
Creates container components▪ Attaches app to store
Provider
React-Redux
<Provider store={this.props.store}>
<App/>
</Provider>
React-Redux Provider
▪ Wraps our component so it’s connected to the Redux store.
Connect
export default connect(
mapStateToProps,
mapDispatchToProps
)(AuthorPage);
onChange() {this.setState({ authors: AuthorStore.getAll() });
}
Flux
componentWillMount() {
AuthorStore.addChangeListener(this.onChange);
}
componentWillUnmount() {
AuthorStore.removeChangeListener(this.onChange);
}
function mapStateToProps(state, ownProps) {
return {appState: state.authorReducer };
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(AuthorPage);
Redux
Benefits:
1. No manual unsubscribe
2. No lifecycle methods required
3. Declare what subset of state you want
4. Enhanced performance for free
connect(mapStateToProps, mapDispatchToProps)
function mapStateToProps(state) {
return {
appState: state
};
}
React-Redux Connect
What state should I expose as props?
▪ Memoize for performance
Reselect
connect(mapStateToProps, mapDispatchToProps)
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(actions, dispatch)
};
}
React-Redux Connect
What actions do I want on props?
this.props.dispatch(loadCourses());
function mapDispatchToProps(dispatch) {
return {
loadCourses: () => {
dispatch(loadCourses());
}
};
}
function mapDispatchToProps(dispatch) {
return {
actions:
bindActionCreators(actions, dispatch)
};
}
Ignore it. Use dispatch.
3 Ways to Handle mapDispatchToProps
Manually wrap
Use bindActionCreators
// In component...
this.props.dispatch(loadCourses())
Two downsides
1. Boilerplate
2. Redux concerns in child components
Option 1: Use Dispatch Directly
function mapDispatchToProps(dispatch) {
return {
loadCourses: () => {
dispatch(loadCourses());
},
createCourse: (course) => {
dispatch(createCourse(course));
},
updateCourse: (course) => {
dispatch(updateCourse(course));
}
};
}
// In component...
this.props.loadCourses()
Option 2: Wrap Manually
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(actions, dispatch)
};
}
// In component:
this.props.actions.loadCourses();
Option 3: bindActionCreators
Wraps action creators in dispatch call for you!
React Hey CourseAction, someone clicked this “Save Course” button.
Action Thanks React! I will dispatch an action so reducers that care can update
state.
Reducer Ah, thanks action. I see you passed me the current state and the action
to perform. I’ll make a new copy of the state and return it.
Store Thanks for updating the state reducer. I’ll make sure that all connected
components are aware.
React-Redux Woah, thanks for the new data Mr. Store. I’ll now intelligently determine
if I should tell React about this change so that it only has to bother with
updating the UI when necessary.
React Ooo! Shiny new data has been passed down via props from the store! I’ll
update the UI to reflect this!
A Chat With Redux
This bullet list is with
animations▪ Container vs Presentation Components
▪ React-Redux
- Provider
- Connect
• mapStateToProps
• mapDispatchToProps
▪ Next up: Let’s code Redux!
Time to code!
@housecor reactjsconsulting.com
Cory House
Async in Redux
This bullet list is with
animations
▪ Why a mock API?
▪ Async libraries
▪ Implement Thunks
Here’s the plan
This slide is with
animations
▪ Start before the API exists
▪ Independence
▪ Backup plan
▪ Ultra-fast
▪ Test slowness
▪ Aids testing
▪ Point to the real API later
Why a Mock API?
▪ Flux
Handed in action
▪ Redux
?
Async
redux-sagaredux-promiseredux-thunk
Redux Async Libraries
▪ Thunks
Functions
Clunky to test
Easy to learn
▪ Sagas
Generators
Easy to test
Hard to learn
Comparison
export function deleteAuthor(authorId) {
return dispatch => {
return AuthorApi.deleteAuthor(authorId).then(() => {
dispatch(deletedAuthor(authorId));
}).catch(handleError);
};
}
Thunk
Demo
This bullet list is with
animations
▪ Let’s get thunky.
This bullet list is with
animations
▪ Thunks, Redux-Promise, and Sagas
▪ Naming async actions
- Consider SUCCESS and ERROR
▪ First thunk, complete!
▪ Next up: Async writes
Wrap Up
Final Thoughts…
The Competition is Responding.
Angular 1 Angular 2 React
Isomorphic x x
Unidirectional x x
1 file per
component
x x
Virtual DOM x x
Hot Reloading x
Browser Support IE8 IE9 IE9
Pluggable x
JSX x
Component Syntax 4 6 10
Yep. But it still won’t be React.
Competition Will Eventually Have All This.
Lightweight, fast, pluggable, isomorphic components in IE8+.
Why React?
Fast
Pluggable
Simple
Testable
Rich Error Messaging
Composable
Broad Browser Support
Isomorphic Friendly
Battle Proven
React Downside
I recently announced my solution…
github.com/coryhouse/react-slingshot
@housecor
There’s much more to be said...
bitnative.com/handouts
Invitation: 5 Minute Retrospective
speakerrate.com@housecor pluralsight.com