JavaRush /Курсы /Модуль 3: React /Настройка React Query для кэширования данных и работы с з...

Настройка React Query для кэширования данных и работы с запросами

Модуль 3: React
19 уровень , 5 лекция
Открыта

При разработке приложения учёта расходов нам всё чаще нужно работать с API: получать список транзакций, отправлять новые данные, обновлять или удалять их. Если делать это вручную через useEffect, useState и Axios — код становится громоздким и повторяющимся.

Решение — React Query (а точнее — TanStack Query). Это мощная библиотека, которая:Решение — React Query (а точнее — TanStack Query). Это мощная библиотека, которая:

  • управляет асинхронными запросами;
  • кэширует ответы;
  • автоматически повторяет неудачные запросы;
  • упрощает логику загрузки, ошибок и обновлений данных.

Установка и настройка React Query

Установка библиотек

Выполним установку двух библиотек: основного пакета и DevTools для отладки.

npm install @tanstack/react-query @tanstack/react-query-devtools

Убедитесь, что Axios тоже установлен:

npm install axios

Создание клиента QueryClient

Каждое приложение на React Query работает с QueryClient — это хранилище для кэша, настроек и состояний запросов.

Создадим файл с его настройками. Файл src/queryClient.ts

import { QueryClient } from '@tanstack/react-query';

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: 2, // Повторить запрос максимум 2 раза при ошибке
      refetchOnWindowFocus: false, // Не делать автозапрос при возвращении в окно
    },
  },
});

export default queryClient;

Подключение провайдера

Подключим QueryClientProvider в корневом файле, чтобы все компоненты могли использовать React Query.

Файл src/main.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import { QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import queryClient from './queryClient';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  </React.StrictMode>
);

Теперь всё готово для использования React Query во всех частях приложения.

Получение данных с useQuery

Начнём с самого простого — загрузки данных с сервера.

Представим, что у нас есть API-эндпоинт /transactions, который возвращает список всех транзакций пользователя. Мы уже умеем писать такие сервисы через Axios.

Файл src/services/transactionService.ts

import api from './api';

export const fetchTransactions = async () => {
  const response = await api.get('/transactions');
  return response.data;
};

Теперь создадим компонент, в котором используем useQuery для загрузки данных:

Файл src/components/TransactionList.tsx

import React from 'react';
import { useQuery } from '@tanstack/react-query';
import { fetchTransactions } from '../services/transactionService';

const TransactionList: React.FC = () => {
  const { data: transactions, isLoading, isError } = useQuery(['transactions'], fetchTransactions);

  if (isLoading) return <p>Загрузка транзакций...</p>;
  if (isError) return <p>Не удалось загрузить данные.</p>;

  return (
    <ul>
      {transactions.map((tx: any) => (
        <li key={tx.id}>
          {tx.date.slice(0, 10)} — {tx.category}: {tx.type === 'income' ? '+' : '-'}${tx.amount}
        </li>
      ))}
    </ul>
  );
};

export default TransactionList;

useQuery делает запрос при монтировании компонента.

  • Что здесь происходит:
  • Ключ запроса — ['transactions'], он нужен для кэширования и обновления.
  • В ответ мы получаем:
    • data — массив транзакций;
    • isLoading — флаг загрузки;
    • isError — флаг ошибки.

Отправка данных с useMutation

Чтобы пользователь мог добавлять новые транзакции, мы будем использовать useMutation.

Шаг 1. Создаём функцию для отправки транзакции

Файл src/services/transactionService.ts

export const createTransaction = async (transaction: Omit<Transaction, 'id'>) => {
  const response = await api.post('/transactions', transaction);
  return response.data;
};

Шаг 2. Используем useMutation в компоненте

Файл src/components/AddTransactionForm.tsx

import React, { useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { createTransaction } from '../services/transactionService';

const AddTransactionForm: React.FC = () => {
  const [amount, setAmount] = useState('');
  const [category, setCategory] = useState('');
  const [type, setType] = useState<'income' | 'expense'>('expense');

  const queryClient = useQueryClient();

  const mutation = useMutation(createTransaction, {
    onSuccess: () => {
      // После успешного запроса обновляем список
      queryClient.invalidateQueries(['transactions']);
    },
  });

  const handleSubmit = () => {
    mutation.mutate({
      category,
      amount: parseFloat(amount),
      type,
      date: new Date().toISOString(),
    });

    setAmount('');
    setCategory('');
  };

  return (
    <div>
      <h3>Добавить транзакцию</h3>
      <input value={amount} onChange={(e) => setAmount(e.target.value)} placeholder="Сумма" />
      <input value={category} onChange={(e) => setCategory(e.target.value)} placeholder="Категория" />
      <select value={type} onChange={(e) => setType(e.target.value as 'income' | 'expense')}>
        <option value="income">Доход</option>
        <option value="expense">Расход</option>
      </select>
      <button onClick={handleSubmit}>Добавить</button>
    </div>
  );
};

export default AddTransactionForm;

Объяснение:

  • useMutation используется для отправки данных (POST-запрос).
  • После успешного выполнения onSuccess обновляет кэш, чтобы список транзакций стал актуальным.
  • queryClient.invalidateQueries(['transactions']) заставляет React Query заново загрузить данные.

Обновление и ручная подгрузка

React Query поддерживает ручное обновление данных:

const { data, refetch } = useQuery(['transactions'], fetchTransactions);

// В интерфейсе:
<button onClick={() => refetch()}>Обновить список</button>

Подключение React Query Devtools

Для отладки очень удобно использовать Devtools — панель, которая показывает статус всех запросов, кэш и прочую информацию.

Добавьте ReactQueryDevtools внутрь QueryClientProvider:

<QueryClientProvider client={queryClient}>
  <App />
  <ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>

Теперь при запуске приложения у вас будет интерфейс для анализа запросов.

Типичные ошибки и рекомендации

Частая ошибка при использовании React Query — забывать обновлять кэш после изменения данных. Например, при добавлении, удалении или изменении транзакций не забывайте вызывать queryClient.invalidateQueries.

Ещё одна популярная ошибка — неправильное назначение ключей запросов. Ключи должны быть уникальными для каждого типа данных. Например, для списка транзакций используйте ['transactions'], а для одной конкретной задачи — ['transaction', id].

2
Задача
Модуль 3: React, 19 уровень, 5 лекция
Недоступна
Запрос данных с помощью React Query
Запрос данных с помощью React Query
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ