Managing Side Effects with Redux-Saga (Part 1)

Tram Ho

If you have learned Redux , between dispatching an action and reducer, we will usually call a certain API from the server, it is likely that the case when the API has not returned the results in time, but the next lines of code have been executed. Exam will lead to false rendering, and to fix that, there is a library that makes it easier to handle this: Redux saga (middleware).

To understand Redux Saga, we will take a look at the basic concepts related to it.

Okay, cloudy, tip. Let’s do it =))


1. Generators first!

To understand sagas, we need to first understand what a generators are. According to the docs :

Generators are functions which can be exited and later re-entered. Their context will be saved across re-entrances. ”

We can think of generator function as an interator. It has a method next () that either returns the next element or will indicate that iteration has been completed on all elements.

DRILL … What is Interator? What mission does it undertake? (yaoming) – If not clear we can refer here remember .

And here is a simple example of a generator, it will return data of type Object:

The structure of the object returned from the generator is very simple – just have the value generated by yield | return, then that value will be assigned to the value property. If there are no additional values ​​then the value property will be undefined and the “done” property will become true (in case the generator’s last element is returned by return).

One important thing that we need to note is that when execute namesEmitter , execution stops when yield hoặc return is called. Execution is resumed from a stopped position when the generator’s next() method is called.

When the data set’s length is unknown, we could write the following:

Okay. Those are the basic concepts of Generator. You can find out more by yourself! Let’s drink a cup and sip water then we continue to learn which sagas.


2. Sagas

Redux-Saga is a redux middleware library, which makes managing side effects in redux apps simpler. By making the most of ES6’s Generators (function *) feature, it allows us to write async code that looks synchronos.

Most of the processing in Reducers is synchronous, but the reality is that there are operations that we must do asynchronously, such as waiting for a request to be used to fetch data and then perform. Next action (change state, dispatch any action …) that is the side effect.

According to the docs :

“Saga is like a separate thread in your application that’s solely responsible for side effects.”

Imagine Saga as a continuous thread that calls the Generator function’s next () method and tries to fetch all the obtained values ​​as quickly as possible. We might be wondering, how does it relate to React and why should we use it? So, we will first see how Saga connects to React / Redux.

A popular React stream powered by Redux-Saga will start with an action. If a reducer is specified to handle this action – the reducer will update the store.

But if a Saga is assigned to handle that action – we usually create a side-effect (like a request to the server), and once done, the Saga sends another action for the reducer to handle, at which point the Reducer. just started updating store.


Common use case

We can illustrate by the following common flow:

The user interacts with the UI (creates the action), which triggers a request to the server. And finally we use the response value (returned from the server) to render the view.

Let’s create an action for each step, and see what it looks like with Redux-Saga:

The next step is to execute a request using the call effect, take a function and an argument, and execute the function using that argument. We’ll provide the call with a “GET” function that executes the server call and returns a promise, which will keep the response on success:

To finish, we dispatch SHOW_DATA_ACTION to update the user interface with the received data.


What happened here?

After the application starts, all Sagas are executed, we can think of it as implementing the Generator function’s next () method until there are no more results. take effect creates something like a sleep thread, which will continue to execute after USER_INTERACTED 1.0.1UI_ACTION is dispatched.

When that happens, it continues to dispatching SHOW_LOADING_ACTION, which will be handled by the reducer. Since Saga is still running, the call effect will run and create a request to the server and Saga will sleep again until the request is answered.


Use it again and again.

In the above example, only one user interaction will be handled by Saga, because after we call put with SHOW_DATA_ACTION there will be nothing left to emit (the done = true property).

If we want to repeat the same action sequence every time USER_INTERACTEDCapUI_ACTION is dispatched, we can do as follows:

This infinite loop will not cause stack overflow and will not damage your client. Since the take effect behaves like a sleep thread, the mySaga execution is pending until the specified action is sent. This works similarly after running into the loop.

Ok. Let’s review the process, step by step:

  1. The application starts and runs all of its existing Saga.
  2. mySaga runs, enters the while (true) loop and ‘sleeping’ on line 3.
  3. USER_INTERACTED 1.0.1UI_ACTION action is dispatched
  4. Saga’s thread wakes up and moves to line 4, where it emits SHOW_LOADING_ACTION for the reducer to be handled (the reducer will now probably cause the view to show loading).
  5. We’ll send a request to the serve (line 5), and sleep until the promise has been resolved with the content stored in the data variable.
  6. SHOW_DATA_ACTION is dispatched along with the received data (variable data), so now the reducer can use it to update state in store.
  7. We go back into the loop and go back to step 2.

Some side effects
  • put : dispatches dispatch 1 action
  • call : Used to call a function. If it returns a promise, suspends the saga until the promise is resolved
  • takeEvery : Execute and return the results of every action called.
  • takeLatest : If we perform a series of actions, it will only return the results of the last actions.
  • Select : Call 1 selector to get data from store.
  • fork : Performs a non-blocking action on the function passed to it.
  • take : Pause until action is received.
  • all : Performs all saga in parallel.

To be continue …. What next?

Since the content is quite long, I will split it into 2 parts and we just went over the content of part 1: some basic concepts related to Redux-Saga and show how it is integrated into the React application.

In the second part … please keep it a secret =)). Please read it.

Thank you so much.

Share the news now

Source : Viblo