JavaRush /Курсы /Модуль 3: React /Что такое Redux Saga и его преимущества перед Thunk

Что такое Redux Saga и его преимущества перед Thunk

Модуль 3: React
7 уровень , 5 лекция
Открыта

Что такое Redux Saga?

Итак, представьте себе оркестр. У вас есть дирижёр (Redux), музыканты (редьюсеры), и всё это звучит как единое целое. Но что, если кто-то решит сыграть соло — например, API-запросы? Вот тут и появляется Redux Saga. Это библиотека, которая берёт на себя роль "оркестратора побочных эффектов". Она помогает вам управлять сложными асинхронными процессами в Redux-приложении, делая это изящным и структурированным образом.

Redux Saga работает на основе JavaScript-генераторов function*, которые позволяют писать асинхронный код так, будто он синхронный. Это делает код легче читаемым и поддерживаемым.

В двух словах:

  • Redux Saga — это middleware для Redux, которое помогает управлять побочными эффектами (например, API-запросами, таймерами, веб-сокетами).
  • Она основана на концепции "саг" — последовательности действий, которые могут быть выполнены асинхронно.

Почему Redux Thunk может быть недостаточным?

Redux Thunk отлично справляется с асинхронными запросами, но по мере роста сложности приложения можно столкнуться с рядом проблем:

  1. Путаница в колбеках: если в приложении есть последовательность из нескольких асинхронных запросов, код начинает напоминать спагетти.
  2. Сложность тестирования: асинхронные действия в Thunk сложнее тестировать, поскольку они зависят от множества сторонних факторов.
  3. Логика смешивается с действиями: в Thunk большая часть асинхронной логики находится в самих действиях, что усложняет их повторное использование.

Redux Saga решает все эти проблемы, предоставляя понятный и декларативный способ описания логики.

Как работает Redux Saga?

Redux Saga интерпретирует генераторы function* и выполняет их шаг за шагом. Это даёт нам возможность писать сложную логику пошагово.

Вот упрощённая схема:

1. Компонент -> отправляет действие (action)
2. Redux -> передаёт действие в Saga Middleware
3. Saga -> исполняет генератор, обрабатывает действие
4. Saga -> вызывает побочные эффекты (API, delay и т.д.)
5. Saga -> отправляет новое действие в Redux
6. Redux -> обновляет Store

Redux Saga использует "эффекты" для взаимодействия с внешним миром. Это функции вроде call, put, takeEvery, которые описывают, какой эффект нужно выполнить.

Преимущества Redux Saga перед Redux Thunk

Давайте сравним Redux Saga и Redux Thunk, чтобы понять, в чём преимущества Saga:

1. Читаемость

Redux Saga позволяет писать асинхронный код последовательно, благодаря использованию генераторов. Вместо вложенных колбеков или цепочек промисов вы получаете линейный код, который легко читать.

Пример с Thunk:

export const fetchData = () => async (dispatch: Dispatch) => {
  dispatch({ type: 'FETCH_REQUEST' });
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    dispatch({ type: 'FETCH_SUCCESS', payload: data });
  } catch (error) {
    dispatch({ type: 'FETCH_FAILURE', error });
  }
};

Пример с Saga:

import { call, put } from 'redux-saga/effects';

function* fetchDataSaga() {
  yield put({ type: 'FETCH_REQUEST' });
  try {
    const data = yield call(fetch, '/api/data');
    yield put({ type: 'FETCH_SUCCESS', payload: data });
  } catch (error) {
    yield put({ type: 'FETCH_FAILURE', error });
  }
}

Видите разницу? Код с Saga более декларативен и проще читается.

2. Мощь генераторов

В отличие от Thunk, Redux Saga позволяет управлять более сложной логикой, вроде параллельных задач, отмены операций или повторных попыток.

Пример с Saga:

import { call, put, takeEvery } from 'redux-saga/effects';

function* retryFetchData() {
  for (let i = 0; i < 3; i++) {
    try {
      const data = yield call(fetch, '/api/data');
      yield put({ type: 'FETCH_SUCCESS', payload: data });
      return;
    } catch (error) {
      if (i < 2) console.log('Retrying...');
      else yield put({ type: 'FETCH_FAILURE', error });
    }
  }
}

function* watchFetchData() {
  yield takeEvery('FETCH_DATA_REQUEST', retryFetchData);
}

3. Легкость тестирования

Redux Saga позволяет тестировать генераторы шаг за шагом, имитируя поведение побочных эффектов.

Пример теста с Saga:

import { call, put } from 'redux-saga/effects';
import { fetchDataSaga } from './sagas';
import { fetch } from './api';

test('fetchDataSaga success', () => {
  const generator = fetchDataSaga();

  expect(generator.next().value).toEqual(put({ type: 'FETCH_REQUEST' }));
  expect(generator.next().value).toEqual(call(fetch, '/api/data'));

  const data = { id: 1 };
  expect(generator.next(data).value).toEqual(put({ type: 'FETCH_SUCCESS', payload: data }));
});

Тесты становятся предсказуемыми, поскольку мы можем контролировать каждый шаг.

4. Поддержка сложных сценариев

Redux Saga превосходно справляется с задачами вроде:

  • Параллельные запросы: выполнение нескольких API-запросов одновременно.
  • Отмена задач: например, отмена загрузки данных при переходе на другой экран.
  • Длительные операции: таймеры, веб-сокеты, обработка неактивных сессий.

Когда использовать Redux Saga?

Redux Saga полезна в следующих случаях:

  1. Сложные асинхронные процессы: нужна обработка последовательности операций или много параллельных задач.
  2. Отмена или перезапуск операций: например, отмена загрузки при закрытии окна.
  3. Повторные попытки: если вы хотите автоматически повторять запросы при неудаче.
  4. Много источников событий: например, веб-сокеты, таймеры, события из нескольких компонентов.

Если же ваше приложение относительно простое и содержит лишь несколько асинхронных действий, Redux Thunk вполне подойдёт.

Установка Redux Saga

Давайте на шаг ближе подойдём к практике. Для начала установим библиотеку и подключим её:

npm install redux-saga

Теперь подключим Saga Middleware в проект:

import createSagaMiddleware from 'redux-saga';
import { configureStore } from '@reduxjs/toolkit';
import rootSaga from './sagas';

const sagaMiddleware = createSagaMiddleware();

const store = configureStore({
  reducer: rootReducer,
  middleware: [sagaMiddleware],
});

sagaMiddleware.run(rootSaga);

export default store;

Redux Saga — это мощный инструмент для управления побочными эффектами в сложных приложениях. Она помогает писать асинхронный код проще, тестировать легче, а поддержку кода делает значительно приятнее.

1
Задача
Модуль 3: React, 7 уровень, 5 лекция
Недоступна
Установка и настройка Redux Saga
Установка и настройка Redux Saga
1
Задача
Модуль 3: React, 7 уровень, 5 лекция
Недоступна
Создание эффекта с Redux Saga
Создание эффекта с Redux Saga
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ