Гид по технологиям

Как использовать Redux Toolkit Query (RTK Query) в React — руководство

6 min read Веб-разработка Обновлено 07 Jan 2026
RTK Query в React: быстрый старт и лучшие практики
RTK Query в React: быстрый старт и лучшие практики

Что вы узнаете

  • Что такое RTK Query и когда его использовать
  • Как настроить apiSlice и store шаг за шагом
  • Примеры кода и улучшения для реального приложения
  • Лучшие практики, тестирование и распространённые ошибки
  • Сравнение с альтернативами и чек-листы для ролей

Код React в редакторе кода

Что такое Redux Toolkit Query

Redux Toolkit Query — это инструмент для запросов данных и кэширования, построенный поверх Redux Toolkit. Он автоматизирует рутинную логику: запросы, кэш, инвалидацию, повторные запросы и управление состоянием загрузки/ошибки. Коротко — делает работу с удалёнными данными более предсказуемой и декларативной.

Определение термина: RTK Query — библиотека для упрощения загрузки и кэширования данных в приложениях на базе Redux.

Ноутбук MacBook с кодом на экране на рабочем столе

Важно: RTK Query не обязательно нужен всем проектам. Для простых локальных состояний и редких запросов достаточно fetch или небольших хуков. RTK Query полезен, когда у вас много связанных эндпоинтов, требуется кэш, инвалидация или централизованное управление состоянием API.

Преимущества RTK Query

  • Интеграция с Redux — единое хранилище для состояния и кэша API
  • Генерация React хуков автоматически по эндпоинтам
  • Кэширование, повторные запросы, инвалидация тегов
  • Поддержка optimistic updates и polling
  • Минимум шаблонного кода

Быстрый старт: установка и запуск

У вас уже может быть проект, созданный через Create React App или Vite. Пример быстрого запуска с CRA:

mkdir React-RTQ
cd React-RTQ
npx create-react-app react-rtq-example
cd react-rtq-example
npm start

Установка зависимостей:

npm install @reduxjs/toolkit react-redux

Определение apiSlice

Api slice — это место, где вы описываете базовый url и набор эндпоинтов (queries и mutations). Простой пример apiSlice, затем улучшенный вариант с тегами и transformResponse.

Исходный пример (переведён и с исправлением возможной опечатки в reducerPath):

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

export const productsApi = createApi({
  reducerPath: "productsApi",
  baseQuery: fetchBaseQuery({ baseUrl: "https://dummyjson.com/" }),

  endpoints: (builder) => ({
    getAllProducts: builder.query({
      query: () => "products",
    }),
    getProduct: builder.query({
      query: (product) => `products/search?q=${product}`,
    }),
  }),
});

export const { useGetAllProductsQuery, useGetProductQuery } = productsApi;

Рекомендации:

  • reducerPath должен быть уникальным и читабельным (например, “productsApi”).
  • Добавляйте providesTags/invalidatesTags для инвалидации кэша при мутациях.
  • Используйте transformResponse, если нужно нормализовать или фильтровать ответ.

Пример улучшенного apiSlice с тегами:

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

export const productsApi = createApi({
  reducerPath: "productsApi",
  baseQuery: fetchBaseQuery({ baseUrl: "https://dummyjson.com/" }),
  tagTypes: ["Products"],
  endpoints: (builder) => ({
    getAllProducts: builder.query({
      query: () => "products",
      providesTags: (result) =>
        result
          ? [
              ...result.products.map((p) => ({ type: "Products", id: p.id })),
              { type: "Products", id: "LIST" },
            ]
          : [{ type: "Products", id: "LIST" }],
    }),
    getProduct: builder.query({
      query: (id) => `products/${id}`,
      providesTags: (result, error, id) => [{ type: "Products", id }],
    }),
    addProduct: builder.mutation({
      query: (newProduct) => ({
        url: "products/add",
        method: "POST",
        body: newProduct,
      }),
      invalidatesTags: [{ type: "Products", id: "LIST" }],
    }),
  }),
});

export const { useGetAllProductsQuery, useGetProductQuery, useAddProductMutation } = productsApi;

Кратко о тегах: providesTags помечает, какие части кэша покрывает query; invalidatesTags говорит RTK Query, что нужно обновить при мутации.

Настройка Redux store

RTK Query добавляет reducer и middleware, которые необходимо подключить в store.

Пример store.js:

import { configureStore } from "@reduxjs/toolkit";
import { productsApi } from "./features/apiSlice";

export const store = configureStore({
  reducer: {
    [productsApi.reducerPath]: productsApi.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(productsApi.middleware),
});

Пояснение: middleware обеспечивает кеширование, подписки и инвалидацию. Без подключения middleware часть возможностей RTK Query работать не будет.

Компонент, использующий RTK Query

Пример компонента Data.js (перевод и объяснение):

import { useGetAllProductsQuery } from "../features/apiSlice";
import React, { useState } from "react";
import "./product.component.css";

export const Data = () => {
  const { data, error, isLoading, refetch } = useGetAllProductsQuery();
  const [productsData, setProductsData] = useState([]);

  const handleDisplayData = () => {
    refetch();
    setProductsData(data?.products);
  };

  return (
    
{isLoading &&
Loading...
} {error &&
Error: {error.message}
} {productsData && productsData.length > 0 && (
    {productsData.slice(0, 4).map((product) => (
  • Name: {product.title}

    Description: {product.description}

    Price: {product.price}

  • ))}
)}
); };

Пояснения:

  • RTK Query возвращает объект с состояниями: data, error, isLoading, isFetching и утилитами, как refetch.
  • Частая ошибка — попытка читать data сразу после вызова refetch. refetch запускает новый запрос асинхронно; используйте isFetching/isLoading для UI.

Обновление App.js

Пример обёртки приложения (Provider + ApiProvider):

import "./App.css";
import { Data } from "./components/Data";
import { store } from "./store";
import { Provider } from "react-redux";
import { ApiProvider } from "@reduxjs/toolkit/query/react";
import { productsApi } from "./features/apiSlice";

function App() {
  return (
    
      
        
); } export default App;

Примечание: ApiProvider позволяет использовать RTK Query без прямого доступа к store, если вы предпочитаете более изолированную конфигурацию. В реализации выше Provider и ApiProvider используются вместе для совместимости и примера.

Когда RTK Query не лучший выбор

  • Если у вас простые одноразовые запросы без кэширования — overhead может быть избыточным.
  • Для очень специфичных потоков данных в реальном времени (WebSocket) RTK Query можно использовать как часть решения, но нативная поддержка потоков требует дополнительной логики.
  • Если вы уже используете полный GraphQL-стек (Apollo Client) — RTK Query даёт преимущества для REST, но не заменит специфичных GraphQL-фич.

Альтернативы

  • React Query (TanStack Query) — сильная библиотека для клиентского кэширования, не привязана к Redux.
  • SWR — минималистичный подход от Vercel.
  • Apollo Client — если вы используете GraphQL.

Короткая рекомендация выбора: выберите RTK Query, если вы уже используете Redux или хотите единое хранилище; выберите React Query, если не используете Redux и хотите независимую библиотеку.

Лучшие практики и эвристики

  • Используйте providesTags/invalidatesTags для гарантированной инвалидации.
  • Нормализуйте данные или используйте id-теги для минимальных повторных загрузок.
  • Обрабатывайте ошибки глобально через слушатели middleware или через существующие UI-компоненты.
  • Переход на TypeScript: опишите типы ответов и используйте generics для createApi и endpoints.
  • Тестирование: мокаем HTTP с msw (Mock Service Worker) и используем mock store.

Ментальная модель: думайте о кэше как о локальном публичном репозитории данных — компоненты читают из него, мутации обновляют и инвалидаируют его.

Чек-лист по ролям

Разработчик:

  • Добавил reducer и middleware в store
  • Определил tagTypes и применил provides/invalidates
  • Обработал состояния isLoading/isFetching/isError
  • Написал unit/e2e тесты для запросов

Code reviewer:

  • Проверил правильность reducerPath
  • Проверил управление тегами и инвалидацию
  • Убедился, что побочные эффекты не происходят в рендерах

QA:

  • Провёл тесты отказоустойчивости (симуляция 500/timeout)
  • Проверил кеширование (повторный запрос не должен обращаться к сети)

PM/PO:

  • Подтвердил требования по времени обновления данных (SLA)
  • Утвердил сценарии оптимистичных обновлений

Тесты и критерии приёмки

Критерии приёмки:

  • Компонент корректно рендерит состояние загрузки, ошибки и данные
  • Повторные вызовы для уже закэшированных данных не вызывают лишних сетевых запросов
  • После мутации соответствующие query инвалидаются и данные обновляются

Минимальные тест-кейсы:

  1. На первой загрузке отображается Loading и затем список продуктов
  2. При симуляции 500 ошибки показывается сообщение об ошибке
  3. После addProduct обновляется список продуктов (инвалидация)

Snippets — быстрые подсказки (cheat sheet)

  • Получить данные и подписаться:
const { data, error, isLoading } = useGetAllProductsQuery();
  • Запустить мутацию:
const [addProduct, { isLoading, error }] = useAddProductMutation();
await addProduct({ title: 'New', price: 100 });
  • Принудительный refetch:
const { refetch } = useGetAllProductsQuery();
refetch();

Производительность и безопасность

  • Кэширование снижает нагрузку на сеть, но следите за объёмом хранимых данных в store.
  • Не храните в редьюсере чувствительные данные в открытом виде. Если передаёте токены, используйте защищённые механизмы и короткий срок жизни токенов.
  • Ограничьте retention времени кэша при больших данных.

Миграция с React Query

Краткие шаги:

  1. Проанализировать используемые хуки и поведение кэша
  2. Перенести логику запросов в createApi endpoints
  3. Настроить теги для инвалидации
  4. Переписать usage на автогенерированные хуки

Сравнение (короткая матрица)

  • RTK Query: отлично для проектов с Redux, встроенный кэш и интеграция
  • React Query: гибкая, независимая, богатая экосистема
  • SWR: простая и лёгкая
  • Apollo: лучший для GraphQL

Частые ошибки и как их избегать

  • Забыт добавить middleware в store — поведение кэша сломается.
  • Использовать refetch и сразу читать data — результат ещё не придёт.
  • Неправильно настроенные теги — инвалидация не сработает.
  • Слишком долго хранить массивы в кэше — OOM/память.

Important: всегда используйте isFetching/isLoading для управления индикаторами загрузки, а данные берите из data только после успешного ответа.

Пример рабочего flowchart для выбора RTK Query

flowchart TD
  A[Нужен ли централизованный state?] -->|Да| B{Используете Redux?}
  A -->|Нет| C[Рассмотрите React Query или fetch]
  B -->|Да| D[RTK Query — предпочтительно]
  B -->|Нет| E[React Query или SWR]

FAQ

Q: Можно ли использовать RTK Query без Redux Provider?

A: Да. ApiProvider позволяет использовать возможности RTK Query без прямого доступа к Redux store, но если вы хотите единое хранилище и использовать другие Redux-редьюсеры, подключайте Provider с store.

Q: Как тестировать компоненты с RTK Query?

A: Используйте msw для мокирования сетевых ответов и configureStore с подключённым productsApi.reducer и middleware для интеграционных тестов.

Заключение

RTK Query — мощный инструмент для работы с удалёнными данными в React-приложениях, особенно если вы уже используете Redux. Он снижает шаблонность кода, улучшает кэширование и делает управление состоянием API предсказуемым. Выберите RTK Query, если вам нужна тесная интеграция с Redux и централизованное управление данными.

Ключевые шаги, чтобы начать:

  • Установить @reduxjs/toolkit и react-redux
  • Создать apiSlice и добавить endpoints
  • Подключить редьюсер и middleware к store
  • Использовать сгенерированные хуки в компонентах

Если нужно, могу предоставить готовый репозиторий с примером, TypeScript-версией и тестами msw.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство