Redux Tutorial

Sean Chang


Why we need Redux?

State management sucks!

Lifting state up

props, props and props...

States are trackable!

Redux time travel

Side effects

Use effects in UI component directly


Container/Presentational Pattern

React Rookie

  • Container: cope with data manipulation & logics
  • Component: focus on UI styles.

Start from a simple App




  • Splitting UI & logics code (maintainability)
  • Lifting states up
  • Make UI components more reusable

CDD (Component driven development)


State management still sucks!

Redux to the rescue!


  • State management
  • Inspired by Flux (One-way data flow)
  • Inspired by elm (Reducers)
  • Command Query Responsibility Segregation (CQRS)
  • Event Sourcing

Flux vs MVC

F8 2014 (Facebook)

The elm architecture

MVU: Model-View-Update


Event sourcing

%%{init: {'themeVariables': {'fontSize': '30px'}}}%% graph LR; A[initialState] --action--> B[stateDiff] B --action--> C[stateDiff] C --action--> D[currentState]

3 Principles

  • Single source of truth (SSOT)
  • State is read-only (Immutable)
  • Changes are made with pure functions (Reducers)


  • Store: store states, dispatch actions
  • Reducer: (State, Action) -> State'
  • Action: javascript object contains type key.
  • Dispatch: only way to change states
  • Selector: (State) -> Data
  • Action Creator: (Payload) -> Action

Understanding Redux from types

One-way data flow

Hands-on Redux








Invisible hand

What Redux Toolkit done for us





Simple App + Redux

The Problems been solved

  • ✅ No longer to lift state up
  • ✅ Finally, We have a state management mechanism
  • ✅ States are trackable
  • ✅ Eliminate side effect in UI

Redux Style Guide

Priority A: Essential

  • Do Not Mutate State (link)
  • Reducers Must Not Have Side Effects
  • Do Not Put Non-Serializable Values in State or Actions
  • Only One Redux Store Per App

So... How can we eliminate the side effects in Redux reducers?

Redux Middleware can do this!

One-way Data Flow with Middleware

Middleware to the rescue!

What is a middleware?

Let's start from a simple log function...

Version 1

Log before & after dispatching an action

Version 2

DRY: don't repeat yourself

Version 3

Monkeypatch: I'm too lazy to import this function every time!

Version 4

We can have many patches

Version 5

Hide mokeypatch

We need to go deeper!

Version 6

Remove monkeypatch: pass the next for me plz!

Redux applyMiddleware API

Version 7



You are able to write a redux middleware!

Apply middlewares to redux store


Data Flow become more complicated!

%%{init: {'themeVariables': {'fontSize': '30px'}}}%% graph LR; A[store.dispatch] --> B[errorHandling] B -->|next| C[logger] C -->|next| D[Reducers]



Side Effects Management


What is a thunk?

"thunks" are a pattern of writing functions with logic inside that can interact with a Redux store's dispatch and getState methods.

Thunk function

Can be synchronize or asynchronize function

Recall the ActionCreator & Dispatch

Rewrite action creator

How do we call the API?

How Does the Thunk Middleware Work?

Thunk Flow

%%{init: {'themeVariables': {'fontSize': '30px'}}}%% graph LR; A[Action] --> B1 A --> B2 subgraph Thunk Middleware B1[function] --> C[Middleware] B2[action] --> C end C -->|next| D[Other Middleware] D -->|next| E[Reducers]


ES6 Generator


Generator function yields Effects (Promise-like objects)


Yield an object and let middleware execute

Effect Creators

Factory functions creating Effects

  • take: Take specific actions from middleware (blocking).
  • call: Send a blocking call request to middleware.
  • put: Send a store.dispatch request to middleware (blocking).
  • fork: Send a non-blocking call request to middleware.

Blocking & Non-Blocking

Advanced Usage

Task cancellation

Saga Helper Functions

  • takeEvery: a high-level API built using take and fork.
  • takeLatest: a high-level API built using take, fork and cancel.

Dive into takeLatest

Two Types of Saga Functions

  • Watcher: generator yield take, .... Register saga worker and listen on specific action type.
  • Worker: generator yield call, put, ....Run jobs defined in worker function.

A common saga worker

%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '30px'}}}%% stateDiagram-v2 direction LR state if_else <> A: call() B: CALL C: put() D: PUT E: put() F: PUT M: Saga Middleware M1: Saga Middleware M2: Saga Middleware [*] --> A A --> B B --> M M --> if_else C --> D E --> F if_else --> E: failed if_else --> C: success D --> M1 F --> M2 M1 --> [*] M2 --> [*]

A common saga worker (cont'd)




Dispatch an action!

%%{init: {'themeVariables': {'fontSize': '20px'}}}%% stateDiagram-v2 direction LR state if_else <> A: dispatch(action) B: takeEvery("USER_FETCH_REQUESTED") C: fetchUser D: call(Api.fetchUser) E: put("USER_FETCH_SUCCESS") F: put("USER_FETCH_FAILED") [*] --> A A --> B B --> C C --> D D --> if_else if_else --> E: success if_else --> F: failed E --> [*] F --> [*]





Testing Reducers

Testing Sagas

Full Example


Furthur Readings