Home >Web Front-end >JS Tutorial >How to make a Redux Saga flow for API calls?

How to make a Redux Saga flow for API calls?

Susan Sarandon
Susan SarandonOriginal
2025-01-20 02:37:13363browse

How to make a Redux Saga flow for API calls?

Use Redux Saga to simplify API workflow in React/React Native projects

This article is not an expert guide, but it will try to explain how to leverage Redux Saga to handle side effects in your React or React Native projects. If your application involves a lot of API calls, Redux Saga can simplify the process and make the code more manageable.

Why choose Redux Saga?

Redux Saga is a middleware that manages side effects (such as API calls) in a clear and predictable way. Instead of stuffing API logic in components or reducers, you can delegate these tasks to saga. Saga allows you to write asynchronous code that looks synchronous, using special JavaScript functions called generators.

Set folder structure

Before delving into saga, be sure to structure your project so it can scale. Here's the basic structure I follow:

  • Services: Contains API endpoints and the functions that call them.
  • Reducers: Manage state changes based on API responses.
  • Sagas: Handle side effects (like API calls) and coordinate work with reducers.
  1. Services: handle API endpoints

The Services folder contains reusable API call functions. Here's an example of the "Change Password" API:

<code class="language-javascript">// ChangePasswordService.js
import {Constants} from '../../Config';
import Ajax from './base';

const BASE_URL = Constants.IS_DEVELOPING_MODE
  ? Constants.BASE_URL.DEV
  : Constants.BASE_URL.PROD;

export default {
  ChangePassword: async params => {
    return fetch(`${BASE_URL}api/change-password`, {
      method: 'POST',
      body: params,
      headers: {
        Accept: 'multipart/form-data',
      },
    })
      .then(response => Ajax.handleResponse(response))
      .then(data => {
        console.log('Data', data);
        return data;
      });
  },
};</code>

Here, we define a ChangePassword function to make API calls. It uses fetch to send a POST request to the endpoint and a helper function (Ajax.handleResponse) to handle the response.

  1. Reducers: Update status

Reducers listen for dispatched actions and update status accordingly. Here is a reducer for managing password changes:

<code class="language-javascript">// PasswordChangeSlice.js
import {createSlice} from '@reduxjs/toolkit';

const passwordChangeSlice = createSlice({
  name: 'passwordChange',
  initialState: {
    data: null,
    isChangeSuccess: null,
    error: null,
    message: null,
  },
  reducers: {
    changePassword: state => {
      state.isChangeSuccess = null;
      state.error = null;
      state.message = '';
    },
    changePasswordSuccess: (state, action) => {
      state.data = action.payload;
      state.message = 'Password changed successfully';
      state.isChangeSuccess = true;
    },
    changePasswordFail: (state, action) => {
      state.error = action.payload;
      state.message = 'Something went wrong';
      state.isChangeSuccess = false;
    },
  },
});

export const {changePassword, changePasswordSuccess, changePasswordFail} =
  passwordChangeSlice.actions;

export default passwordChangeSlice.reducer;</code>

This reducer has three actions:

  • changePassword: Reset state when request starts.
  • changePasswordSuccess: Update status with success data.
  • changePasswordFail: Update status with error information.
  1. Sagas: Managing Side Effects

Now to the point! The Saga handles the actual API calls and dispatches actions based on the responses. Here is a saga for the "Change Password" API:

<code class="language-javascript">import {all, call, put, takeEvery} from 'redux-saga/effects';
import API from '../Services/ChangePasswordService';
import {
  changePasswordFail,
  changePasswordSuccess,
} from '../Reducers/PasswordChangeSlice';

function* changePasswordSaga({payload}) {
  try {
    const response = yield call(API.ChangePassword, payload);
    if (response?.data) {
      yield put(changePasswordSuccess(response.data));
    } else if (response?.errors) {
      yield put(changePasswordFail(response.errors));
    }
  } catch (error) {
    yield put(changePasswordFail(error.message));
  }
}

function* passwordSaga() {
  yield all([
    takeEvery('passwordChange/changePassword', changePasswordSaga),
  ]);
}

export default passwordSaga;</code>
  • call: Call the API function (API.ChangePassword) and wait for the result.
  • put: dispatch actions to update status.
  • takeEvery: Listen to a specific action (changePassword) and trigger the corresponding worker saga (changePasswordSaga).

If the API call succeeds, the saga will emit changePasswordSuccess; if it fails, changePasswordFail will be emitted.

  1. Hooks: Connect components

To trigger the process, we create a custom hook to dispatch the changePassword action:

<code class="language-javascript">// useChangePasswordActions.js
import {useDispatch, useSelector} from 'react-redux';
import {changePassword} from '../Reducers/PasswordChangeSlice';

export const useChangePasswordActions = () => {
  const dispatch = useDispatch();
  const passwordState = useSelector(state => state?.changePassword);

  const changePasswordCall = params => {
    dispatch(changePassword(params));
  };

  return {
    passwordState,
    changePasswordCall,
  };
};</code>

How it works

  • Action distribution: The component calls changePasswordCall in the custom hook.
  • Reducer: changePassword action updates the status to indicate that the request is in progress.
  • Saga: watcher saga listens to changePassword and triggers worker saga.
  • API calls: The worker saga calls the ChangePassword API and handles the response.
  • Status update: The saga distributes the success or failure action and updates the status through the reducer.

Summary

This setup organizes your API workflow into clear and manageable steps:

  • Services handle API logic.
  • Reducers update status.
  • Sagas handle side effects and glue everything together.

Remember, this is just one way to organize your project. If you have more experience or ideas, please feel free to comment with your strategies. I will cover more about saga in future articles as I learn and improve.

Happy programming! ?

The above is the detailed content of How to make a Redux Saga flow for API calls?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn