---
title: Redux и асинхронность
seo:
  title: Redux и асинхронность — React Developer
  description: Тема «Redux и асинхронность» для собеседования React Developer. Какие преимущества дает использование Redux для управления состоянием приложения? Что такое Redux Thunk?
---

[Все темы React Developer](/react-developer)

## <strong>Какие преимущества дает использование</strong> <code>Redux</code> <strong>для управления состоянием приложения?</strong> [#q-14bee738d69b811aa2e1f7058a5fa6ea]

Преимущества использования <code>Redux</code> для управления состоянием приложения&#58;

{/* prettier-ignore */}
1. <strong>Предсказуемость состояния</strong>&#58;

    - Состояние приложения централизовано и управляется через чистые функции (редьюсеры), что делает поведение предсказуемым.

1. <strong>Отладка и инструменты</strong>&#58;

    - Redux DevTools предоставляет мощные инструменты для отладки и анализа изменений состояния.

1. <strong>Централизованное управление состоянием</strong>&#58;

    - В store хранится выбранное общее состояние. Локальное состояние интерфейса можно оставить в компонентах.

1. Чистые редьюсеры&#58;

    - Redux делает приложение более детерминированным, что упрощает тестирование и отладку.

1. <strong>Масштабируемость</strong>&#58;

    - Подходит для больших и сложных приложений благодаря четкой структуре и разделению логики.

1. <strong>Сообщество и экосистема</strong>&#58;

    - Большая поддержка со стороны сообщества и наличие множества middleware и инструментов.

:::note[Ссылки для изучения]

1. [Использование Redux в React](https://rajdee.gitbooks.io/redux-in-russian/content/docs/basics/UsageWithReact.html)
   :::

---

## <strong>Что такое</strong> <code>Redux Thunk</code><strong>?</strong> [#q-14bee738d69b81378f5ee83fd54b891c]

Redux Thunk позволяет передавать в dispatch функцию. Middleware вызывает её с dispatch и getState; внутри можно выполнять синхронную логику или асинхронную работу и отправлять обычные actions. Thunk action creator обычно возвращает такую функцию.

#### Основные функции&#58;

{/* prettier-ignore */}
1. <strong>Обработка асинхронных операций</strong>&#58;

    - Позволяет выполнять асинхронные запросы внутри действий.

    - Пример&#58;

        ```javascript
        const fetchData = () => {
          return async (dispatch) => {
            const response = await fetch('https://api.example.com/data');
            const data = await response.json();
            dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
          };
        };
        ```

1. <strong>Доступ к dispatch и getState</strong>&#58;

    - Позволяет внутри thunk-функции вызывать <code>dispatch</code> и <code>getState</code> для управления состоянием.

    - Пример&#58;

        ```javascript
        const fetchData = () => {
          return (dispatch, getState) => {
            const state = getState();
            // Логика на основе текущего состояния
          };
        };
        ```

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

:::note[Ссылки для изучения]

1. [Использование Redux в React](https://rajdee.gitbooks.io/redux-in-russian/content/docs/basics/UsageWithReact.html)
   :::

---

## <strong>Как работает</strong> <code>Redux Saga</code><strong>?</strong> [#q-14bee738d69b81b0882aee3a026a67a0]

<code>Redux Saga</code> — это middleware для управления побочными эффектами в
Redux с использованием генераторов ES6.

#### Основные функции&#58;

{/* prettier-ignore */}
1. <strong>Генераторы ES6</strong>&#58;

    - Использует функции-генераторы для управления асинхронным кодом.

    - Пример&#58;

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

        function* fetchData() {
          try {
            const response = yield call(fetch, 'https://api.example.com/data');
            if (!response.ok) throw new Error(`HTTP ${response.status}`);
            const data = yield call([response, response.json]);
            yield put({ type: 'FETCH_DATA_SUCCESS', payload: data });
          } catch (error) {
            yield put({ type: 'FETCH_DATA_FAILURE', payload: error.message });
          }
        }

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

1. <strong>Эффекты Saga</strong>&#58;

    - Операторы, такие как <code>call</code>, <code>put</code>, <code>takeEvery</code>, упрощают управление побочными эффектами.

    - Пример&#58;

        ```javascript
        function* fetchDataExample() {
          const response = yield call(fetch, 'https://api.example.com/data');
          if (!response.ok) throw new Error(`HTTP ${response.status}`);
          const data = yield call([response, response.json]);
          yield put({ type: 'FETCH_DATA_SUCCESS', payload: data });
        }
        ```

1. <strong>Создание Saga Middleware</strong>&#58;

    - Подключение saga middleware к Redux store.

    - Пример&#58;

        ```javascript
        import createSagaMiddleware from 'redux-saga';
        import { applyMiddleware, createStore } from 'redux';
        import rootSaga from './sagas';

        const sagaMiddleware = createSagaMiddleware();
        const store = createStore(reducer, applyMiddleware(sagaMiddleware));

        sagaMiddleware.run(rootSaga);
        ```

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

:::note[Ссылки для изучения]

1. [Использование Redux в React](https://rajdee.gitbooks.io/redux-in-russian/content/docs/basics/UsageWithReact.html)
   :::

---

## <strong>Как реализовать ленивую загрузку</strong> <code>Redux</code><strong>-редьюсеров?</strong> [#q-14bee738d69b81aebad7ec5c975ca02e]

Для реализации ленивой загрузки <code>Redux</code>-редьюсеров используйте функцию <code>replaceReducer</code> и динамический импорт.

#### Шаги&#58;

{/* prettier-ignore */}
1. <strong>Создайте хранилище Redux с начальным редьюсером</strong>&#58;

    ```javascript
    import { createStore } from 'redux';
    const initialReducer = (state = {}, action) => state;
    const store = createStore(initialReducer);
    ```

1. <strong>Функция для добавления новых редьюсеров</strong>&#58;

    - Реализуйте функцию для динамического добавления редьюсеров.

    ```javascript
    const asyncReducers = {};

    const createRootReducer = (asyncReducers) => {
      return combineReducers({
        // добавьте синхронные редьюсеры здесь
        ...asyncReducers
      });
    };

    store.asyncReducers = asyncReducers;

    store.injectReducer = (key, asyncReducer) => {
      store.asyncReducers[key] = asyncReducer;
      store.replaceReducer(createRootReducer(store.asyncReducers));
    };
    ```

1. <strong>Динамический импорт редьюсера и его добавление</strong>&#58;

    ```javascript
    import { lazy } from 'react';

    const loadReducer = async (store) => {
      const { default: newReducer } = await import('./path/to/newReducer');
      store.injectReducer('newReducer', newReducer);
    };

    const MyComponent = lazy(() => import('./MyComponent'));
    ```

1. <strong>Использование в компоненте</strong>&#58;

    - Дождитесь loadReducer(store) до первого рендера компонента, читающего эту часть состояния. useEffect ниже запускается после первого commit и сам по себе этого не гарантирует.

    ```javascript
    useEffect(() => {
      loadReducer(store);
    }, []);
    ```

Для ленивой загрузки Redux-редьюсеров используйте <code>replaceReducer</code>, динамический импорт и функцию для добавления новых редьюсеров в хранилище.

:::note[Ссылки для изучения]

1. [Использование Redux в React](https://rajdee.gitbooks.io/redux-in-russian/content/docs/basics/UsageWithReact.html)
   :::
