> For the complete documentation index, see [llms.txt](https://gpeterhand.gitbook.io/react/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gpeterhand.gitbook.io/react/redux/redux-saga.md).

# Redux saga

**Источники**

* Nader Dabit. [Redux 4 Ways . Implementations of Thunk vs Saga vs Observable vs Redux Promise Middleware in 10 minutes](https://medium.com/react-native-training/redux-4-ways-95a130da0cdc) \[20 февраля 2017]
* Esteban Herrera. [Разбираемся в redux-saga: От генераторов действий к сагам](https://habr.com/post/351168/) \[12 октября 2017]

Устанавливаем redux-saga (1.0.0-beta.1). Также нужно установить и подключить [**regenerator-runtime**](https://github.com/facebook/regenerator/tree/master/packages/regenerator-runtime). Иначе, в консоли будет ошибка *"Uncaught ReferenceError: regeneratorRuntime is not defined"*

> yarn add redux-saga\@next regenerator-runtime

Создаем экшен, сагу и связываем их вместе

{% code title="src/scenes/Home/services.js" %}

```jsx
// ...
import { call, put, takeEvery } from 'redux-saga/effects'

// Action
export const FETCH_REQUEST = 'FETCH_REQUEST'
// ...

// Saga
function* fetch() {
  try {
    yield put({ type: SHOW_PRELOADER })
    const {
      data: { text }
    } = yield call(
      axios,
      'https://hacker-news.firebaseio.com/v0/item/121003.json'
    )
    yield put({ type: CHANGE_TEXT, text })
  } catch ({ message }) {
    //
  } finally {
    yield put({ type: HIDE_PRELOADER })
  }
}
export const homeSagas = [takeEvery(FETCH_REQUEST, fetch)]

// ...
```

{% endcode %}

Навешиваем экшен на кнопку

{% code title="src/scenes/Home/index.js" %}

```jsx
// ...
import { FETCH_REQUEST } from './services'

// ...
<Button variant="raised" onClick={() => dispatch({ type: FETCH_REQUEST })}>
  Saga: CHANGE TEXT
</Button>
// ...
```

{% endcode %}

Собираем все саги в одной корневой саге (здесь же раннее мы собрали и все редьюсеры)

{% code title="src/App/services" %}

```jsx
import { combineReducers } from 'redux'
import { all } from 'redux-saga/effects'

import { home, homeSagas } from 'scenes/home/services'

// Reducers
export const rootReducer = combineReducers({ home })

// Sagas
export function* rootSaga() {
  yield all([...homeSagas])
}
```

{% endcode %}

Подключаем все это к стору и запускаем саги

{% code title="" %}

```jsx
// ...
import 'regenerator-runtime/runtime'
import createSagaMiddleware from 'redux-saga'

import { rootReducer, rootSaga } from './services'

const sagaMiddleware = createSagaMiddleware()

const store = createStore(
    ...
    applyMiddleware(
      routerMiddleware(history), // for dispatching history actions
      thunk,
      sagaMiddleware
      // ... other middlewares ...
    )
  )
)

sagaMiddleware.run(rootSaga)

...
```

{% endcode %}

Запускаем. Жмем кнопку. Текст должен загрузится и отобразиться

**Примечание:** если дальше будем использовать **redux-saga**, то **redux-thunk** можно удалить из проекта
