Tips to build a Todo app with react, redux-saga, typescript and react-bootstrap — 2

Canhua Li
3 min readDec 7, 2021

--

This is a follow up on Tips to build a Todo app with react, redux-saga, typescript and react-bootstrap — 1 | by Canhua Li | Nov, 2021 | Medium

Source code: licanhua/react-todo: A todo project with `react` + `typescript` + `redux-saga` + `react-bootstrap` (github.com)

Module-Actions

In last chapter, we created actions and the todo reducer slice like below.

Actions

There are three kinds of actions:

  1. data update only action. For example, loadToDosError and loadToDosSuccess.
  2. command only action. For example, saveToDos.

3. both data update and command action. For example: loadToDos. It first reset the data, then execute the command.

No matter the action is updating data or executing a command. They are dispatched to the store in the same way.

In reality, most of time, the command is async function. If you are using redux thunk middleware, you can refer to Redux Fundamentals, Part 6: Async Logic and Data Fetching | Redux to see how the async command is dispatched and handled. I will discuss how saga receive the command and execute it in next chapter.

Redux-saga

In my opinion, redux-saga is the soldiers, they are always standby and wait for the commander’s order. For example, the commander said: moveToTheVillage in half an hour. After the soldier take the order, he acknowledge the command, and then drive to the village, then report the status: moveToTheVillageComplete. For some reason, he didn’t make it, then he reported: moveToTheVillageTimeout.

So the execution of the soldier is represented as a saga like this

Soldier folllows the order

And the soldier is waiting for the order like this:

soldier is wait for the order

And the commander send out the order like this:

Commander orders moveToVillage

Keep saga clean

saga should be very clean, and always keep the actual execution in a function. Otherwise it’s hard to do the testing, and lost the best feature redux-saga give you.

like api.saveToDos, it may only have one line of code

localStorage.setItem(TODOS, JSON.stringify(todos));

Don’t have above line in the saga, but put it into a function like api.saveToDos.

clean saga

then you are able to test the saga like this

Test save

Saga Testing

You can refer to my code src\sagas\index.test.ts. also Error Handling | Redux-Saga and Testing | Redux-Saga are good for you to start.

Component/Container testing

Because the nature of using hooks(useSelector/useDispatch) in React component. Below are good candidates for you:

Testing: React hooks, Redux and Jest — Tom Szpytman — Medium

reactjs — How to test a component using react-redux hooks? — Stack Overflow

import * as redux from 'react-redux'

const spy = jest.spyOn(redux, 'useSelector')
spy.mockReturnValue({ username:'test' })

reactjs — mock useDispatch in jest and test the params with using that dispatch action in functional component — Stack Overflow

jest.mock('react-redux', () => ({
useSelector: jest.fn(),
useDispatch: () => mockDispatch
}));

--

--