Reduce, Reuse, Redux
An intro to Redux (mostly without React)
http://codepen.io/collection/DYWRkW/
https://slides.com/justindragos/redux/live#/
Justin Dragos @EllisandePoet
Problem
http://codepen.io/ellisande/pen/amJYVw
Solution
Blame Moment
Moment is Stupid
- I can't believe they did that
- This is deeply unfair to me
- I'm quitting open source forever
- 183902332 + 64000 = tomorrow?
Disclaimer: I love Moment
Disclaimer: I love Moment
Problem
http://codepen.io/ellisande/pen/ZpZxrL
Solution
Blame JavaScript
Stupid Arrays
- Legacy code is awful
- Probably written in a weekend
- {theRight: 'way'}
Disclaimer: I don't hate JS Arrays that much
Disclaimer: I love JavaScript
Problem
http://codepen.io/ellisande/pen/VKbwjr
Solution
We Need a Library!
Hard Problems
- Mutable State
- Race conditions
- Listening for state change
- Interface for state change
Redux to the Rescue!
It can help with:
- None of it
- Nadda
- Zilch
- Well Maybe...
What is Redux?
State Manager
- Defines How Data Flows
- Creates a Single Source of Truth
- Creates a Single Source of Change
- Forces a Discretely Testable Mutation Functions
Background
- Created by Dan Abramov
- Originally an Experiment in Time Travel
- No Initial Connection with React
- 23k Stars on Github
- 7M Downloads on NPM
Redux Flow
Action
Reducer
New State
Dispatch
Store
Subscribe
Action
- Fully Serializable Object
- Must have a 'type' field
Action
const updateUserName = {
type: 'UPDATE_USER_NAME',
newName: 'Justin'
};
Action Creator
//Function that returns an action
const updateUserName = newName => {
return {
type: 'UPDATE_USER_NAME',
newName
};
};
//Create the action, then dispatch to the store
myAppStore.dispatch( updateUserName('Justin') );
Reducer
- Pure Function
- Does Not Mutate Current State
- Only State Changer
- Takes
- Action
- Current State
- Returns
- New State
Reducer
const myReducer = (currentState, action) => {
//State can't change, just always return current
return currentState;
}
Reducer
const myReducer = (currentState, action) => {
//Tell the reducer how to handle appropriate actions
if(action.type === 'UPATE_USER_NAME'){
//The new state
return {
userName: action.newName
};
}
//Return current state if we don't care about the action
return currentState;
}
Reducer
const myReducer = (currentState, action) => {
const newState = Object.assign({}, currentState);
//Tell the reducer how to handle appropriate actions
if(action.type === 'UPATE_USER_NAME'){
//The new state
newState.userName = newName;
}
//Will be current state if no actions matched
return newState;
}
Reducer Immutability
//Bad because you are mutating current state
const myReducer = (fans, action) => {
if(action.type === 'ADD_FAN'){
fans.push(action.newFan);
}
return fans;
}
//Good because you are not mutating the existing array
const myReducer = (fans, action) => {
if(action.type === 'ADD_FAN'){
return [...fans, action.newFan];
}
return fans;
}
Store
- Current State
- Reducers
- Subscriptions
- Middleware
Store Methods
//Dispatch an action to the store
myAppStore.dispatch( myAction );
//Get current state
myAppStore.getState();
//Create the store (one time)
const myAppStore =
redux.createStore( reducer, initialState, middleware );
//Listener is called when state changes
myAppStore.subscribe( listener );
Problem Part Redux
http://codepen.io/ellisande/pen/amJYVw
Choose
- Patterns
- Middleware
- React
- Time Travel
- Multiple Stores
Patterns
Combine Reducers
const myReducer = Redux.combineReducers({
//Reducer for *just* the userName part of state
userName: (currentName, action) => {
//Only get passed the old userName
if(action.type === 'NEW_USER'){
//I just return the new userName
return action.userName;
}
//Just return the new user name
return currentName;
});
Combine Reducers
Large Reducer:
http://codepen.io/ellisande/pen/pEWxOw
Smaller Reducer:
http://codepen.io/ellisande/pen/ozGaPm
Sharing Types
http://codepen.io/ellisande/pen/zKEmya?editors=0011
Middleware
Good Uses
- Logging
- Async actions
- Validation
- Unwrap Functions
Middleware
const logger = store => next => action => {
//Your chance to do something before the action is processed
const updatedAction = next(action);
//Your chance to do something after the action is processed
return updatedAction;
}
React
React-Redux
- Exposes a Higher Order Component (HOC)
- State Comes in as Props
- Can Transform State on the Way in
React Flow
Action
Reducer
New State
Dispatch
Store
Subscribe
Props
Component
Events
React Redux
import {connect} from 'react-redux';
class ShowMe {
render(){
return (<div>Hello from {this.props.userName}!</div>);
}
};
export default connect(i=>i)(ShowMe);
/*
state structure:
{
userName: 'Justin'
}
*/
React-Redux
http://codepen.io/ellisande/pen/WGkYwE
Time Travel
Time Travel Example
https://github.com/Ellisande/time-travel
Multiple Stores
Syncing Stores
UI
UI
Store
Sever
Store 1
Store 2
Store 3
Store 4
Action
Action
Questions?
- @EllisandePoet
- Redux: http://redux.js.org/
- Slides:
- https://slides.com/justindragos/redux
- Pens:
- http://codepen.io/collection/DYWRkW/
- Time Travel
- https://github.com/Ellisande/time-travel
Reduce, Reuse, Redux
By Justin Dragos
Reduce, Reuse, Redux
An introduction to Redux mostly without React.
- 2,393