Redux!
Predictable state container for JavaScript apps
Structure of this talk
- Basic concepts
- API overview
- Some advanced stuff you can do
- Recap and useful learning model
Why Redux?
Single state atom
{
"todos": [
{
"text": "Listen to this talk",
"completed": true
},
{
"text": "Read the docs",
"completed": false
},
{
"text": "Try Redux",
"completed": false
}
],
"visibilityFilter": "SHOW_ALL"
}
Actions
{
"type": "ADD_TODO",
"text": "Try Redux"
}
Reducers
(oldState, action) => newState
Functions are pure and nothing is destroyed
State 1
State 2
State 3
Action A
Action B
The view is derived
from the state
State
View
Actions
Redux API
The store
import {createStore} from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
store.subscribe(() => {
console.log("New state is:", store.getState())
})
store.dispatch({type: "MY_ACTION"})
Action creators
- Pure helper functions that return an action
export const addTodo = (text) => {
return {
type: 'ADD_TODO',
text
}
}
Reducers
const initialState = {foo: "bar", bar: "baz"}
const reducer = (state = initialState, action) => {
switch (action.type) {
case 'SET_FOO':
return {
...state,
foo: action.foo
}
default:
return state
}
}
Multiple reducers
import {combineReducers} from 'redux'
import todos from './todos'
import visibilityFilter from './visibilityFilter'
export default combineReducers({
todos,
visibilityFilter
})
Usage with React
import {connect} from 'react-redux'
import TodoList from '../components/TodoList'
export default connect(
mapStateToProps, // aka selector
mapDispatchToProps // or action creators hash
)(TodoList)
Selectors
appState => componentProps
Advanced selectors
- memoizee (two e's)
- reselect
- (but not Ramda memoize)
Async actions
- REQUEST
- RESPONSE
- ERROR
Middleware
Intercept dispatched actions
Thunk middleware
export function asyncActionCreator() {
return (dispatch, getState) => {
// ...
}
}
Async example
export function asyncActionCreator() {
return dispatch => {
dispatch({type: "REQUEST"})
fetch("/my-resource")
.then(processResponse)
.then(results =>
dispatch({type: "RESPONSE", results}))
.catch(error =>
dispatch({type: "ERROR", error}))
}
}
More stuff
you can do
Redux logger middleware
Redux devtools
const store = createStore(todoApp, window.devToolsExtension && window.devToolsExtension())
React devtools
Save state to localStorage
Analytics middleware
Server-side rendering
Performance
- shouldComponentUpdate()
- Wrap a stateless components
- Potential upcoming PureComponent
- connect() only re-renders on change
Exceptions to state being in one place
- Minor UI state
- Google "Thinking in React"
- redux-form for repeated patterns
- URL state (maybe...)
Things I'm interested in learning about next
- MobX
- Observables/RxJS
- Elm
Dreyfus model
of skill acquisition
5. Expert
4. Proficient
3. Competent
2. Advanced beginner
1. Novice
Google it for a free chapter from "Pragmatic Thinking and Learning"
1. Novice
- Great docs and tutorials
- Clear recipe to follow
- Very popular/good community
- "Safe choice"
2. Advanced beginner
- Each concept understandable in isolation
- Can actually get stuff done
- Again, good docs
3. Competent
- Can "take initiative" and plan out a complex app
- Unlikely to regret choosing Redux
- "Don't use a boilerplate"
4. Proficient
- One framework among many
- Key maxims/concepts
- Single state atom
- Everything is pure functions
- Notice things that other people think are important
5. Expert
???
The end
Redux!
By David Moody
Redux!
- 457