GetQueryData всегда возвращает неопределенное значение, даже если установлено с помощью useMutation — TanStack Query, React

Когда я пытаюсь прочитать содержимое кэша данного ключа, я получаю неопределенное значение даже после того, как вызываю useMutation с точно таким же ключом.

Мутация, используемая для установки кеша (мутация возвращает правильные данные, как и ожидалось):

const axiosInstance = axios.create(habiticaAPIconf);

function parseResponse(response:LoginDataContract):AuthData{
  return {
    id: response.data.id,
    apiToken: response.data.apiToken,
    username: response.data.username
  }
}

const getAuthenticationData = async (userCredentials:UserCredentials):Promise<AuthData> => {
  const response = await axiosInstance.post<LoginDataContract>("/user/auth/local/login", {...userCredentials});
  return parseResponse(response.data);
}

export function useCredentialData() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (loginData:UserCredentials):Promise<AuthData> => getAuthenticationData(loginData),
    mutationKey: ['authData']
  });
};

Компонент, используемый для запуска мутации:

export function LoginForm() {
  const { mutate, isSuccess, data } = useCredentialData();

  function handleLogin(e: MouseEvent<HTMLButtonElement, globalThis.MouseEvent>) {
    e.preventDefault();
    mutate({
      username: (document.getElementById("email") as HTMLInputElement).value,
      password: (document.getElementById("password") as HTMLInputElement).value
    });
    console.info(data);
  }

  return (
    <form>
      <label htmlFor = "email">
        <input type = "email" name = "email" id = "email"></input>
      </label>
      <label htmlFor = "password">
        <input type = "password" name = "password" id = "password"></input>
      </label>
      <button type = "submit" onClick = { (e)=> {handleLogin(e)}}>Login</button>
      <span>{isSuccess ? `${data.username}` : ""}</span>
    </form>
  )
}

При нажатии кнопки в компоненте React всегда возвращается неопределенное значение даже после вызова вышеупомянутой мутации и возвращает правильные данные.

import { useQueryClient } from "@tanstack/react-query";

export function SidebarTasksList() {
  const queryClient = useQueryClient();

  return (
    <section>
      <button onClick = {
        ()=>console.info(queryClient.getQueryData(['authData']))
      }>CLICK</button>
    </section>
  );

Как получить данные, хранящиеся в кеше ['AuthData']? Также нет функции, которую я мог бы передать useQuery как queryFn, поэтому я использую getQueryData.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вообще говоря, mutations и queries не имеют никакой корреляции. Установка одного и того же ключа на них обоих не приведет к тому, что они узнают друг о друге. mutationKey также не является обязательным. Ни один из примеров на самом деле не устанавливает ключ, если я правильно помню, потому что он в основном используется для обмена конфигурацией между мутациями.

Чтобы «связать» результат ваших мутаций с вашими запросами, вам нужно либо:

  • сделать запрос недействительным в ответ на успешную мутацию. Это путь с наименьшим количеством кода, поскольку он будет просто повторно получен с сервера:
  return useMutation({
    mutationFn: (loginData:UserCredentials):Promise<AuthData> => getAuthenticationData(loginData),
    onSuccess: () => queryClient.invalidateQueries(['authData'])
  });
  • если ваш вызов API возвращает данные, вы можете использовать их для ручной записи в кеш. Это больше кода, но на один путь к серверу меньше:
  return useMutation({
    mutationFn: (loginData:UserCredentials):Promise<AuthData> => getAuthenticationData(loginData),
    onSuccess: (data) => queryClient.setQueryData(['authData'], data)
  });

Первое предложение очень похоже на anitpattern, даже если API, с которым я работаю, не будет возвращать данные, я бы использовал setQueryData, второй подход работал отлично.

jazzgot 30.08.2024 20:21

Инвалидацию очень рекомендуется делать, потому что это наименьший объем кода, и он всегда будет работать, даже если вы добавите код позже. Попытка оптимизировать минимальное количество сетевых запросов кажется немного неоптимальной.

TkDodo 31.08.2024 11:18

Ладно, думаю, мы немного не поняли друг друга. В API я работаю с единственным способом получения учетных данных — с помощью почтового вызова, как я делаю в функции getAuthenticationData . В моем коде с ключом authData нет определения useQuery. В данном случае, если я правильно понимаю: инвалидация приведет либо к очистке authData кеша, либо ни к чему (потому что queryFn не назначено authData). Итак, теперь я думаю, что вместо useMutation мне следует использовать useQuery и передать туда почтовый вызов как querFn. Как вы думаете, это лучший подход?

jazzgot 31.08.2024 20:16

Другие вопросы по теме