TASIOMIND.DEV — OPERATIONAL▸▸▸FULL STACK DEVELOPER @ GWQ SERVICEPLUS AG▸▸▸FOUNDER — K8SGPT.AI▸▸▸OPEN SOURCE: ACTIVE▸▸▸DISTRIBUTED SYSTEMS / KUBERNETES / AI▸▸▸RUST + GO + PYTHON▸▸▸FIELD TESTED / STATUS — NOMINAL▸▸▸LOCATION: EUROPE/BERLIN▸▸▸TASIOMIND.DEV — OPERATIONAL▸▸▸FULL STACK DEVELOPER @ GWQ SERVICEPLUS AG▸▸▸FOUNDER — K8SGPT.AI▸▸▸OPEN SOURCE: ACTIVE▸▸▸DISTRIBUTED SYSTEMS / KUBERNETES / AI▸▸▸RUST + GO + PYTHON▸▸▸FIELD TESTED / STATUS — NOMINAL▸▸▸LOCATION: EUROPE/BERLIN▸▸▸

Getting started with Redux Saga

December 9, 2019

You can not make API calls (or any other side effects) inside the reducers. For that you must use middleware. Redux Saga is one such middleware, which is good for

  • async things like data fetching
  • impure things like accessing browser cache

Generator functions

Redux Saga uses Generator functions, an ES6 feature.

With ES6 generators, we have a different kind of function, which may be paused in the middle, one or many times, and resumed later, allowing other code to run during these paused periods.

  • They are denoted with a *, e.g. function* foo() {}
  • We pause function with the yield keyword, from inside the function
  • We restart the function from the outside, can not be restarted from within the function once it's paused
code
function* foo() {
  // code goes here
}

Concepts

Watcher and worker sagas

code
// Worker
function* getUsers() {
  try {
  } catch (e) {}
}

// Watcher
function* watchGetUsers() {
  yield takeEvery(users.actions.getUsers, getUsers); // when this action is dispatched, run this function
}

Blocking and non-blocking sagas

BlockingNon-blocking
takeEvery

Common effects

  1. call() makes a function call. Could be another generator, or an API call, or a helper function imported from another file. We can yield a Promise directly,
code
const products = yield Api.fetch('/products')

but that makes unit testing difficult. So we use call() instead

code
// call(fn, ...args)
const products = yield call(Api.fetch, '/products')