How to Write Your First Redux-Saga

Chirag Patel/ August 5, 2021/ Uncategorized

Nowadays, Redux saga became the most popular library to handle asynchronous requests and control the application flow in redux, so In this article, we will discuss what is redux-saga, what is the benefits of using it, and also discuss how to use redux-saga.

What is a redux-saga?

Redux-saga is middleware which is handle side effects and asynchronous request in redux.  

Redux without redux-saga
Action(s) -> Reducer(s)

Redux with redux-saga
Actions(s) -> Redux saga -> Reducer(s)

Generators
Generators are the core concept of the redux-saga so before discussing how redux-saga works, we need to understand what is generators and how it works?

Generators are functions that can be paused and resumed, instead of executing all the statements of the function in one pass.

When you invoke a generator function, it will return an iterator object, With each call of the iterator’s next() method, the generator’s body will be executed until the next yield statement and then pause, [More].
Let’s see a basic example of the generators

function* generators() {
  yield 1;
  yield 2;
}

// calling
const gen = generator();

// use
console.log(gen.next()); // {value: 1, done: false}
console.log(gen.next()); // {value: 2, done: false}
console.log(gen.next()); // {value: undefined, done: true}

See the above code, we observe that calling the generator function doesn’t execute the whole function definition, but instead of that it’s a return iterator object. When iterator’s next() method is called, the function body is executed until the first yield.
next()  method returns the object with a value and done property, value contains the yielded value and done contain the generator has yielded its last value or not as a boolean.
Ok, So we have enough discussed generators, now we are going to create our first saga.

Create Saga

Before creating a saga we will add redux-saga middleware in our redux store.

import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import reducers from './reducers';
import rootSaga from './sagas';

// saga middleware
const sagaMiddleware = createSagaMiddleware()
const store = createStore(
  reducers,
  applyMiddleware(sagaMiddleware)
)
// run saga
sagaMiddleware.run(rootSaga)

Above is the basic code of the how-to setup redux store with redux-saga middleware.

Now, we create our Saga files.
Saga files are mainly split into two parts
1. Watcher
2. Workers

  • Watcher Saga watches every dispatch action and if it matches the action then handle that action and assign it to the saga worker.
  • Worker saga handles all the side effects.
  • In root-saga, we import watcher saga and mount on the redux store,

Let’s understand with an example: 

// Watcher
export function* watchBulkConnect() {
  yield takeEvery('BULK_CONNECT_FETCH_DATA_EFFECT', getBulkConnectList);
}

// Worker
function* getBulkConnectList() {
 const data = yield call(apifetchProfiles);
 yield put({ 
   type: 'BULK_CONNECT_SUCCESS_DATA_STATE', 
   payload: data
 });
}

See above example,
Watcher Saga listing to BULK_CONNECT_FETCH_DATA_EFFECT and when this action type dispatched watcher saga called getBulkConnectList saga which is a worker and worker saga on first yield call some API and get the results and next yield, dispatch another action type which is BULK_CONNECT_SUCCESS_DATA_STATE with payload which contains previous yield results.
Here, takeEvery, call and put are provided by the redux-saga library itself to handle/dispatch redux effects.
You can check more creator functions here.

Reference: 

https://redux-saga.js.org/docs/introduction/GettingStarted
https://redux.js.org/recipes/reducing-boilerplate#actions