Day 4: Handling Side Effects with Redux-Saga


In this tutorial, you’ll learn how to integrate Redux-Saga into your React Native app and manage asynchronous side effects such as API requests using sagas. By the end of today’s lesson, you’ll have replaced Redux Thunk with Redux-Saga for managing asynchronous actions in your app.


What You Will Learn Today:

  1. Installing and setting up Redux-Saga
  2. Creating sagas to handle side effects
  3. Dispatching actions with sagas
  4. Using takeEvery and call effects in Redux-Saga
  5. Testing Redux-Saga with an API call

Step 1: Installing Redux-Saga

To begin using Redux-Saga, you’ll need to install the redux-saga package and set it up in your Redux store.

  1. Install redux-saga:
npm install redux-saga
  1. Modify your Redux store to configure Redux-Saga. Open store/store.js and update it as follows:
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from './reducers';
import rootSaga from './sagas'; // We will create this next

// Create the saga middleware
const sagaMiddleware = createSagaMiddleware();

// Create the Redux store with saga middleware
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));

// Run the root saga
sagaMiddleware.run(rootSaga);

export default store;

Explanation:

  • createSagaMiddleware(): Initializes the Redux-Saga middleware, which will handle running your sagas.
  • sagaMiddleware.run(rootSaga): Runs the root saga where all your individual sagas will be combined.
  • applyMiddleware(sagaMiddleware): Adds the Redux-Saga middleware to your Redux store.
See also  Day 7: Testing and Optimizing for Different Screen Sizes (Responsive Design)

Step 2: Creating Sagas to Handle Side Effects

Let’s now create sagas that will handle the side effects, such as fetching data from an API. Sagas are generator functions that yield effects to describe what should happen (e.g., making an API call or dispatching an action).

  1. Inside the store folder, create a new folder called sagas, and inside it, create a file called postSagas.js:
mkdir store/sagas
touch store/sagas/postSagas.js
  1. Open postSagas.js and create the saga to fetch posts:
import { call, put, takeEvery } from 'redux-saga/effects';

// Worker saga: makes the API call when the watcher saga sees the action
function* fetchPostsSaga() {
  try {
    const response = yield call(fetch, 'https://jsonplaceholder.typicode.com/posts');
    const data = yield response.json();
    yield put({ type: 'FETCH_POSTS_SUCCESS', payload: data });
  } catch (error) {
    yield put({ type: 'FETCH_POSTS_FAILURE', error: error.message });
  }
}

// Watcher saga: watches for actions dispatched to the store and starts the worker saga
export function* watchFetchPosts() {
  yield takeEvery('FETCH_POSTS_REQUEST', fetchPostsSaga);
}

Explanation:

  • fetchPostsSaga: This is the worker saga that performs the actual API request when triggered. It uses the call effect to call the fetch function and the put effect to dispatch either a success or failure action.
  • watchFetchPosts: This is the watcher saga that listens for FETCH_POSTS_REQUEST actions. When such an action is dispatched, it runs the fetchPostsSaga.
  • call(): Effect that makes the API call in a saga.
  • put(): Effect that dispatches an action in a saga.
  • takeEvery(): Watches for every occurrence of a specified action and runs the corresponding worker saga.

Combining Sagas

We’ll now combine the sagas into a rootSaga that the Redux store will use.

  1. Inside the sagas folder, create a file called index.js:
touch store/sagas/index.js
  1. Open index.js and combine the sagas:
import { all } from 'redux-saga/effects';
import { watchFetchPosts } from './postSagas';

// Root saga: combines all the individual sagas into one
export default function* rootSaga() {
  yield all([watchFetchPosts()]);
}

Explanation:

  • all(): Effect that runs multiple sagas concurrently. In this case, it combines the watchFetchPosts saga with any other sagas you may add in the future.
See also  Day 5: Implementing Authentication with JWT in React Native

Step 3: Dispatching Actions with Sagas

Let’s now dispatch the FETCH_POSTS_REQUEST action from a component to trigger the saga and fetch posts from the API.

  1. Open Posts.js and modify it to dispatch the FETCH_POSTS_REQUEST action:
import React, { useEffect } from 'react';
import { View, Text, ActivityIndicator, FlatList } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';

export default function Posts() {
  const dispatch = useDispatch();
  const { posts, loading, error } = useSelector((state) => state.posts);

  useEffect(() => {
    dispatch({ type: 'FETCH_POSTS_REQUEST' }); // Dispatch the saga action
  }, [dispatch]);

  if (loading) {
    return <ActivityIndicator size="large" color="#0000ff" />;
  }

  if (error) {
    return (
      <View>
        <Text>Error: {error}</Text>
      </View>
    );
  }

  return (
    <FlatList
      data={posts}
      keyExtractor={(item) => item.id.toString()}
      renderItem={({ item }) => (
        <View style={{ padding: 10 }}>
          <Text style={{ fontWeight: 'bold' }}>{item.title}</Text>
          <Text>{item.body}</Text>
        </View>
      )}
    />
  );
}

Explanation:

  • We replaced the thunk-based action dispatch with the saga-based action by dispatching { type: 'FETCH_POSTS_REQUEST' }. This triggers the watchFetchPosts saga, which in turn runs fetchPostsSaga to fetch the posts.

Step 4: Testing Redux-Saga with an API Call

With Redux-Saga now set up, let’s test the asynchronous action flow by running the app and fetching posts from the API.

  1. Run your app:
npm start
  1. You should see the loading spinner while the data is being fetched. Once the data is fetched successfully, the list of posts should be displayed. If there’s an error, it will be shown on the screen.

Step 5: Recap and Summary

In today’s tutorial, you learned how to manage asynchronous side effects using Redux-Saga in a React Native app. Here’s a quick summary of what you’ve done:

  • Installed and set up Redux-Saga in your Redux store.
  • Created worker and watcher sagas to handle asynchronous operations.
  • Used effects like call, put, and takeEvery to manage side effects in Redux-Saga.
  • Replaced Redux Thunk with Redux-Saga to fetch posts from an API and update the Redux state.
  • Tested Redux-Saga with API requests and displayed the fetched data in your app.
See also  Day 1: Deploying a Serverless API on AWS Lambda

With Redux-Saga in place, your app can now handle complex side effects like API requests in a more powerful and scalable way.


Next Up: Day 5 – Implementing Authentication with JWT in React Native

In Day 5, we’ll implement authentication with JWT (JSON Web Tokens) in your React Native app. You’ll learn how to handle user login, secure routes, and store authentication tokens securely.

Stay tuned for more advanced features tomorrow!


Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.