Редукс Сага

Redux Saga — это библиотека промежуточного программного обеспечения для Redux, которая позволяет вам управлять побочными эффектами (например, асинхронными запросами API) более организованным и декларативным способом. Вот краткое руководство по использованию Redux Saga:

  1. Установить Редукс Сага
npm install redux-saga

2. Создайте сагу Сага — это функция, которая прослушивает действие и выполняет некоторый побочный эффект. Чтобы создать Saga, вам нужно определить функцию генератора, используя синтаксис function*.

import { takeEvery, put, call } from 'redux-saga/effects';
import { fetchSuccess, fetchError } from './actions';
import { FETCH_DATA } from './constants';
import api from './api';

function* fetchData() {
  try {
    const data = yield call(api.fetchData);
    yield put(fetchSuccess(data));
  } catch (error) {
    yield put(fetchError(error));
  }
}

function* mySaga() {
  yield takeEvery(FETCH_DATA, fetchData);
}

export default mySaga;

В этом примере мы определяем сагу с именем fetchData. Эта сага прослушивает действие FETCH_DATA и выполняет вызов API, используя эффект call. Если вызов API успешен, он отправляет действие fetchSuccess, используя эффект put. Если есть ошибка, он отправляет действие fetchError, используя эффект put.

Функция mySaga — это корневая сага, которую мы будем использовать для запуска всех наших саг. В этом примере мы используем эффект takeEvery для прослушивания всех действий FETCH_DATA и вызова саги fetchData.

3. Используйте промежуточное ПО Saga. Чтобы использовать промежуточное ПО Saga, вам необходимо применить его к вашему магазину Redux при его создании.

import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from './reducers';
import mySaga from './sagas';

const sagaMiddleware = createSagaMiddleware();

const store = createStore(
  rootReducer,
  applyMiddleware(sagaMiddleware)
);

sagaMiddleware.run(mySaga);

export default store;

В этом примере мы создаем хранилище Redux и применяем промежуточное ПО Saga, используя applyMiddleware. Мы также передаем нашу корневую сагу методу run промежуточного программного обеспечения, который запускает сагу и слушает все действия, которые необходимо обработать.

Вот и все! С помощью этих простых шагов вы можете начать использовать Redux Saga для управления побочными эффектами в вашем приложении Redux. Конечно, с Redux Saga вы можете делать гораздо больше, например, использовать другие эффекты, такие как takeLatest, fork или select. Но это краткое руководство должно дать вам хорошее представление о том, с чего начать.

4. Действия по отправке Теперь, когда мы определили нашу Saga и применили промежуточное программное обеспечение, мы можем отправлять действия из наших компонентов, чтобы вызвать побочный эффект. Например, предположим, что у нас есть компонент, которому нужно получить некоторые данные из API при его монтировании.

import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import { fetchData } from './actions';

function MyComponent({ fetchData }) {
  useEffect(() => {
    fetchData();
  }, []);
  return (
    <div>
      {/* render component */}
    </div>
  );
}
export default connect(null, { fetchData })(MyComponent);

В этом примере мы определяем компонент с именем MyComponent и используем хук useEffect для отправки действия fetchData при монтировании компонента. Мы подключаем компонент к хранилищу Redux с помощью функции connect из библиотеки react-redux и сопоставляем действие fetchData со свойствами компонента.

Когда отправляется действие fetchData, ПО промежуточного слоя Saga перехватывает его и запускает fetchData Saga, которая выполняет вызов API и отправляет соответствующие действия на основе результата.

5. Тестируйте саги Наконец, важно протестировать саги, чтобы убедиться, что они работают должным образом. Redux Saga предоставляет утилиту для тестирования под названием redux-saga-test-plan, которая упрощает тестирование ваших саг.

import { expectSaga } from 'redux-saga-test-plan';
import { fetchData, fetchSuccess } from './actions';
import { fetchData as fetchDataSaga } from './sagas';
import api from './api';

it('fetches data from API and dispatches success action', () => {
  const data = [1, 2, 3];
  const action = fetchData();
  
  return expectSaga(fetchDataSaga, action)
    .provide([      [call(api.fetchData), data],
    ])
    .put(fetchSuccess(data))
    .run();
});

В этом примере мы определяем тест, который проверяет, извлекает ли fetchData Saga данные из API и отправляет действие fetchSuccess. Мы используем функцию expectSaga из redux-saga-test-plan для тестирования Saga и предоставляем фиктивную реализацию вызова API с использованием метода provide.

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

Расширенное использование

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

Разветвление саг: саги могут быть разветвлены для запуска независимо друг от друга. Это полезно, когда вам нужно одновременно обрабатывать несколько асинхронных действий.

import { take, fork } from 'redux-saga/effects';

function* watchAndLog() {
  while (true) {
    const action = yield take('*');
    console.log('action', action);
  }
}
function* rootSaga() {
  yield fork(watchAndLog);
}

В этом примере мы определяем Saga с именем watchAndLog, которая регистрирует все действия, отправленные на консоль. Мы используем эффект fork для запуска этой саги независимо от других саг в корневой саге.

  • Объединение саг: саги можно комбинировать с помощью эффекта all для обработки нескольких действий в одной саге.
import { all, call, put, takeEvery } from 'redux-saga/effects';

function* fetchData(action) {
  try {
    const data = yield call(api.fetchData, action.payload);
    yield put(fetchSuccess(data));
  } catch (error) {
    yield put(fetchError(error));
  }
}
function* postData(action) {
  try {
    const response = yield call(api.postData, action.payload);
    yield put(postSuccess(response));
  } catch (error) {
    yield put(postError(error));
  }
}
function* rootSaga() {
  yield all([
    takeEvery(FETCH_DATA, fetchData),
    takeEvery(POST_DATA, postData),
  ]);
}

В этом примере мы определяем две саги с именами fetchData и postData, которые обрабатывают действия FETCH_DATA и POST_DATA соответственно. Мы используем эффект takeEvery, чтобы прослушивать эти действия и вызывать соответствующие саги. Затем мы используем эффект all, чтобы объединить эти саги в одну корневую сагу.

  • Отмена Саги: Саги можно отменить с помощью эффекта cancel. Это полезно, когда вам нужно остановить запуск саги в ответ на определенное действие.
import { take, call, cancel, fork } from 'redux-saga/effects';

function* watchFetchData() {
  while (true) {
    const { payload } = yield take(FETCH_DATA);
    const task = yield fork(fetchData, payload);
    yield take(CANCEL_FETCH_DATA);
    yield cancel(task);
  }
}
function* fetchData(payload) {
  // fetch data
}
function* rootSaga() {
  yield fork(watchFetchData);
}

В этом примере мы определяем сагу с именем watchFetchData, которая прослушивает действие FETCH_DATA и разветвляет сагу fetchData для ее обработки. Мы используем эффект take, чтобы прослушивать действие CANCEL_FETCH_DATA, и эффект cancel, чтобы остановить запуск саги fetchData.

Заключение
Redux Saga предоставляет множество мощных функций для управления побочными эффектами в вашем приложении Redux. Комбинируя саги и используя расширенные эффекты, такие как fork, all и cancel, вы можете с легкостью обрабатывать сложные асинхронные потоки. С помощью библиотеки redux-saga и утилит тестирования, таких как redux-saga-test-plan, вы можете создавать надежные и надежные приложения, которые легко обрабатывают асинхронные действия.