Redux-Saga with TypeScript in React Native application

vixita markana
Simform Engineering
5 min readSep 18, 2023

Supercharge your React Native app with Redux-Saga and TypeScript

Redux is an excellent state management framework, usually used with React Native. But have you thought about Redux-Saga?

In this blog post, we will discuss how to use Redux-Saga with TypeScript.

But first things first.

What is Saga?

Saga is middleware used for managing complex asynchronous processes, preventing unnecessary API calls, better handling of failures, and making it easier to test.

Additionally, Saga acts as a separate thread to your application, listening for specific actions from your main application to perform complex asynchronous tasks and updating your application’s state once it is completed. We can organise side effects (i.e., talking to a backend server, impure things like accessing the browser cache, etc.) in a way that is easier to manage, more efficient to execute, and easier to run.

Redux-Saga is used for large applications with complex logic. However, it is unnecessary for smaller applications.

Flow of Redux-Saga | GIF by Chirpy_me

TypeScript extends JavaScript by adding data types, classes, and other object-oriented features with type-checking. It is a typed superset of JavaScript that compiles into plain JavaScript.

Before we embark on this Redux-Saga adventure, let’s ensure we’re well-equipped.

Here’s a quick checklist of the essential libraries you’ll need:

Now, let’s create a project and install the dependencies.

Create a React Native application

Let’s create a project in TypeScript using the below command:

npx react-native init AwesomeProject
  • Install redux and redux-saga

To manage the state and achieve side effects, install the necessary dependencies:

yarn add redux react-redux redux-saga
  • Install Dev Dependencies

Install the TypeScript dev dependencies using the following command:

yarn add --dev @types/react-redux @types/redux-saga
  • Install apisauce / reduxsauce

apisauce is a low-fat wrapper for the amazing axios http client library built with TypeScript.

reduxsauce is used to create the reducer, and it is a library that provides concise methods for writing action, creators, and reducers.

yarn add apisauce reduxsauce

A User Sign-in Example

Here are the key steps we’ll follow:

Create Action

Create Reducer

Create Store

Create Saga

Create Root-Saga

Step 1: Create Action

We will use the createAction method to create our actions and return creators and their corresponding types.

redux/signInUser/SignInUserReducer.ts

The argument of createAction is an object, and the keys are the names of the action. The value is an array of strings that is the name of the payload, or null if there is no payload.

There are three types of actions to call the APIs. Each action has a specific role — send a request to API with a payload (signInRequest), celebrate successful response (signInSuccess), and handle failures (signInFailure).

Step 2: Create Reducer

A reducer is a pure function that contains the business logic to produce a state. It accepts the initial state and returns a new state with a computed value.

redux/signInUser/SignInUserReducer.ts

The first argument of a createReducer is the initial state of the Redux store, while the second argument is an object. The object keys, which are all action types, should be capitalized and separated by underscores.

The initial object has three properties: data, error, and fetching. The data is used for API success response, the error is used for API failure response, and fetching is a loading state for API calls.

If we use Redux-Saga with TypeScript, we need to specify the type of every action.

Step 3: Create Store

A store is an object form that contains the application state tree. We can change the store by dispatching an action.

redux/Store.ts

We’ll create a Redux middleware using the createSagaMiddleware method and connect our Sagas to the Redux store.

The run method can be used to run Saga only after the applyMiddleware phase.

The createStore function’s first argument is a combine-all reducer, and the second is the application's middleware.

We can add one or more middleware in the applyMiddleware function.

Step 4: Create Saga

So, here we will use the generator function to handle side effects from the fetch request.

saga/AuthSaga.ts

A generator function is defined using the function* expression, and the yield* operator is used to delegate to the generator function.

The yield operator is used to pause and resume a generator function.

In TypeScript, we need to provide the types of every API response to use the ApiResponse interface imported from the apisauce library.

If we use the signInUser function as a generator, we don’t need to use promises.

The Redux-Saga includes methods such as call, put, take, fork, and select. The put method is used for dispatching store actions, and the call method is used for calling a promise and waiting until the promise is fulfilled.

Here is the successful response from the sign-in API:

Sign-in API Response
  • Create Root-Saga

The apisauce provides numerous methods such as get, post, put, delete, head, etc.

services/Api.ts

After creating a saga, we will import all sagas associated with our application and create a root saga.

saga/index.ts

We can use the all() method to execute multiple effects simultaneously while waiting for them to finish, similar to a Promise.all() function.

There are many methods of Redux-Saga, such as take, takeEvery, takeLatest, cancel, and cancelled. The takeLatest method works when an action is dispatched to the store. If a pattern is matched, then a new saga is started in the background.

Consider a scenario where a user clicks the sign-in button multiple times and a saga task has already been started. In this case, the previous task is automatically canceled by yield cancel, allowing the latest saga to take precedence.

We can use the store in the root file to be used on all screens.

The App.tsx file looks like this:

App.tsx

We can fetch the data using useSelector, and use useDispatch for dispatching actions.

redux/useRedux.ts

We have separated the auth selector into different states, such as getLoading, getError, and getUser.

redux/signInUser/SignInUserSelector.ts

In the SignInScreen, we can call the API and use a selector to fetch the API data.

modules/SignInScreen.tsx

The types interface is located in the Types.ts file.

Types.ts

Over to You

Redux-Saga is more efficient in dealing with complex use cases. It improves error handling, simplifies testing, and can handle multiple tasks simultaneously without waiting for any of them to finish, making it a more robust solution for managing asynchronous Redux operations.

For the complete source code, check out the GitHub repository.

For more updates on the latest tools and technologies, follow the Simform Engineering blog.

Connect with us: Twitter | LinkedIn

--

--