Intro to
Redux.
Marcin Śpiewak, Marek Mitis
Is ReactJS state enough?
componentDidMount(){
this.state = {
prop1: 'value',
prop2: 'value',
};
}
Props, props everywhere.
Root Application Component
Search Input Component Result List Component
Item
Component
Item
Component
Item
Component
Props, props everywhere.
Root Application Component
Search Input Component Result List Component
Item
Component
Item
Component
Item
Component
Props, props everywhere.
Root Application Component
Search Input Component Result List Component
Item
Component
Item
Component
Item
Component
Props, props everywhere.
Root Application Component
Search Input Component Result List Component
Item
Component
Item
Component
Item
Component
Redux to the rescue?
Three main Redux principles
➔ Single source of thruth
➔ State of the app is read-only
➔ Changes are made with pure functions
Redux structure
Action
View
Component
Reducer Store
Redux structure
Action
View
Component
Reducer Store
dispatch(action)
Redux structure
Action
View
Component
Reducer Store
dispatch(action)
Middlewares
Redux structure
Action
View
Component
Reducer Store
dispatch(action) updates(reducer)
Middlewares
Redux structure
Action
View
Component
Reducer Store
dispatch(action) updates(reducer)
render(state)
Middlewares
Some more details
➔ Unidirectional flow (forget „two-way” binding).
➔ Based on Flux concept.
➔ Easy injectable into any ReactJS project.
➔ 99 lines of code.
➔ Keep it flat.
Differences with Flux
➔ Only one store
➔ Dispatcher replaced with reducers
„Old school”
Root Application Component
Search Input
Component
Result List Component
Item
Component
Item
Component
Item
Component
Redux driven architecture
Root Application Component
Search Input
Component
Result List Component
Item
Component
Item
Component
Item
Component
Redux
Store
Pros of React & Redux stack
➔ Awesome debug & testability
➔ Strong community & support
➔ Cross-platform architecture
➔ It’s Immutable(JS)!
Actions
export function addNewTask (task) {
return {
type : 'NEW_TASK_ADD', // name of the action
payload : task // data sent as 'payload'
}
}
Actions
export function addNewTask (task) {
return {
type : 'NEW_TASK_ADD', // name of the action
payload : task // data sent as 'payload'
}
}
Actions
export function addNewTask (task) {
return {
type : 'NEW_TASK_ADD', // name of the action
payload : task // data sent as 'payload'
}
}
Reducer
export default function reducer(state = { tasks : []}, action) {
switch (action.type) {
case 'NEW_TASK_ADD':
return { tasks : [...state.tasks, action.payload] }
default:
return state;
}
}
Reducer
export default function reducer(state = { tasks : []}, action) {
switch (action.type) {
case 'NEW_TASK_ADD':
return { tasks : [...state.tasks, action.payload] }
default:
return state;
}
}
Reducer
export default function reducer(state = { tasks : []}, action) {
switch (action.type) {
case 'NEW_TASK_ADD':
return { tasks : [...state.tasks, action.payload] }
default:
return state;
}
}
Reducer
export default function reducer(state = { tasks : []}, action) {
switch (action.type) {
case 'NEW_TASK_ADD':
return { tasks : [...state.tasks, action.payload] }
default:
return state;
}
}
Store
import { combineReducers, createStore } from 'redux';
import reducer from './reducers/index';
const allReducers = combineReducers({
tasks : reducer
});
let store = createStore(allReducers);
Store
import { combineReducers, createStore } from 'redux';
import reducer from './reducers/index';
const allReducers = combineReducers({
tasks : reducer
});
let store = createStore(allReducers);
Store
import { combineReducers, createStore } from 'redux';
import reducer from './reducers/index';
const allReducers = combineReducers({
tasks : reducer
});
let store = createStore(allReducers);
Store base functions
// subscribing
store.subscribe(function(){
/* .. something changed in store */
});
// dispatching
store.dispatch(action);
That powerful Middlewares
const consoleReporter = store => next => action => {
console.log("Dispatched action: ", action)
return next(action)
}
That powerful Middlewares
const consoleReporter = store => next => action => {
console.log("Dispatched action: ", action)
return next(action)
}
That powerful Middlewares
const consoleReporter = store => next => action => {
console.log("Dispatched action: ", action)
return next(action)
}
The best of middlewares
➔ Thunk
➔ Logger
➔ DevTools
Bind React with Redux (part I)
import { Provider } from 'react-redux';
ReactDOM.render(
<Provider store={store}>
<AppViewContainer />
</Provider>,
document.getElementById('root')
);
Bind React with Redux (part II)
import addNewTask from './actionCreators'
import { bindActionCreators } from 'redux'
function mapStateToProps(state) {
return { tasks: state.tasks }
}
function mapDispatchToProps(dispatch) {
return { actions: bindActionCreators( { addNewTask }, dispatch) }
}
export default connect(mapStateToProps, mapDispatchToProps)(AppComponent)
How to debug Redux flow?
Chrome plugin: ReduxDevTools.
Livecoding
„React-Redux”
Let’s replace Redux with our own
implementation
Thank you for the workshop :)
We need your feedback !

Intro to Redux | DreamLab Academy #3