> 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/axios.md).

# redux-thunk, axios

Асинхронные запросы к внешним API

* **redux-thunk** - выполнение асинхронных действий в Redux
* **axios** - HTTP-клиент для браузера и node.js, основанный на промисах

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

Flavio Copes. [HTTP requests using Axios](https://flaviocopes.com/axios/) \[4 апреля 2018]

Устанавливаем [**axios**](https://github.com/axios/axios)

> yarn add axios

Пример использования:

```javascript
    axios
    .get('https://hacker-news.firebaseio.com/v0/item/121003.json')
    .then(({ data: { text } }) => dispatch({ type: FETCH_SUCCESS, text }))
    .catch(() => {})
    .then(() => dispatch({ type: HIDE_PRELOADER }))
```

Можно использовать как **async/away**. Однако, для этого нужно подключить библиотеку [babel-polyfill](https://babeljs.io/docs/usage/polyfill/). А она занимает около **90Kb**. Так что, пока воздержимся.

```javascript
async function getUser() {
  try {
    const response = await axios.get('/user?ID=12345');
    console.log(response);
  } catch (error) {
    console.error(error);
  }
}
```

#### Когда, откуда и как отправлять асинхронные запросы? <a href="#kogda-otkuda-i-kak-otpravlyat-asinkhronnye-zaprosy" id="kogda-otkuda-i-kak-otpravlyat-asinkhronnye-zaprosy"></a>

**Вариант 1 - непосредственно из компонента.**

Чем плохо? Бизнес-логика не отделена от компонента

**Вариант 2 - из экшена**

Наверное, самый распространенный вариант. Однако,для этого нужно сначала установить и подключить миделвару [redux-thunk](https://github.com/gaearon/redux-thunk)

Устанавливаем

> yarn add redux-thunk

Подключаем:

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

```javascript
...
import thunk from 'redux-thunk'

...
  composeEnhancers(
    applyMiddleware(
      routerMiddleware(history), // for dispatching history actions
      thunk
      // ... other middlewares ...
    )
...
```

{% endcode %}

Пишем thunk, добавляем экшены, корректируем редьюсер

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

```javascript
import axios from 'axios'

// Actions
const SHOW_PRELOADER = 'SHOW_PRELOADER'
const HIDE_PRELOADER = 'HIDE_PRELOADER'
const CHANGE_TEXT = 'CHANGE_TEXT'

// Thunks
export const getText = () => dispatch => {
  dispatch({ type: SHOW_PRELOADER })
  axios
    .get('https://hacker-news.firebaseio.com/v0/item/121003.json')
    .then(({ data: { text } }) => dispatch({ type: CHANGE_TEXT, text }))
    .catch(() => {})
    .then(() => dispatch({ type: HIDE_PRELOADER }))
}

// Reducer
export const home = (state = {}, action) => {
  switch (action.type) {
    case SHOW_PRELOADER:
      return { ...state, preloader: true }
    case HIDE_PRELOADER:
      return { ...state, preloader: false }
    case CHANGE_TEXT:
      return { ...state, text: action.text }
    default:
      return state
  }
}
```

{% endcode %}

Корректируем компонент Home

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

```jsx
import { connect } from 'react-redux'
import Button from '@material-ui/core/button'

import { getText } from './services'

const Home = ({ preloader, text, dispatch }) => (
  <>
    <h1>Home</h1>
    <p>{text}</p>

    {preloader && <p>Загрузка...</p>}
    <Button variant="raised" onClick={() => dispatch(getText())}>
      CHANGE TEXT
    </Button>
  </>
)

export default connect(({ home }) => ({ ...home }))(Home)
```

{% endcode %}

**Вариант 3 - Redux saga**

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

Будет рассмотрен в дальнейших главах
