Реагировать -вопрос о запросе и недействительности запроса

#reactjs #react-query

#reactjs #реагирующий запрос

Вопрос:

Я действительно не знаю, как четко задать вопрос, но сначала я вставлю свой код и спрошу ниже.

 function useToDos() {
  const queryCache = useQueryCache();
  const fetchTodos = useQuery(
    'fetchTodos',
    () => client.get(paths.todos).then(({ data }: any) => data),
    { enabled: false }
  );

  const createTodo = async ({ name ) =>
    await client.post(paths.todos, { name }).then(({ data }) => data);

  return {
    fetchTodos,
    createTodo: useMutation(createTodo, {
      onMutate: newItem => {
        queryCache.cancelQueries('fetchTodos');
        const previousTodos = queryCache.getQueryData('fetchTodos');
        queryCache.setQueryData('fetchTodos', old => [
          ...old,
          newItem,
        ]);
        return () => queryCache.setQueryData('fetchTodos', previousTodos);
      },
    }),
  };
}
  

Как вы можете видеть, я пытаюсь создать свои собственные пользовательские хуки, которые переносят функциональность react-query. Из-за этого мне нужно отключить мой fetchTodos запрос, чтобы он не выполнялся сразу. Однако нарушает ли это всю выборку фоновых данных?

В частности, когда я запускаю createTodo и onMutate запускаю метод, я бы в идеале хотел, чтобы fetchTodos обновление запроса выполнялось в фоновом режиме, чтобы мой список задач во внешнем интерфейсе обновлялся без повторной отправки запроса. Но, похоже, что при изначально отключенном запросе фоновое обновление не вступает в силу.

Поскольку я не думаю, что перенос перехватов react-query в библиотеку пользовательских перехватов — отличная идея, у меня, вероятно, будет больше вопросов об этой же настройке, но пока я начну здесь. Спасибо. 😊

Ответ №1:

Мутация автоматически не запускает повторную выборку. Способ добиться этого с помощью react-query — использовать QueryCache.invalidateQueries для аннулирования кэша после мутации. Из документов:

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

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

 function useToDos() {
  const queryCache = useQueryCache();
  const fetchTodos = useQuery(
    'fetchTodos',
    () => client.get(paths.todos).then(({ data }: any) => data),
    { enabled: false }
  );

  const createTodo = async ({ name ) =>
    await client.post(paths.todos, { name }).then(({ data }) => data);

  return {
    fetchTodos,
    createTodo: useMutation(createTodo, {
      onMutate: newItem => {
        queryCache.cancelQueries('fetchTodos');
        const previousTodos = queryCache.getQueryData('fetchTodos');
        queryCache.setQueryData('fetchTodos', old => [
          ...old,
          newItem,
        ]);
        return () => queryCache.setQueryData('fetchTodos', previousTodos);
      },

      onSettled: () => {
        cache.invalidateQueries('fetchTodos');
      }

    }),
  };
}
  

Комментарии:

1. В чем разница между invalidateQueries и refetchQueries ?

2. Look like invalidateQueries — это просто лучший вариант refetchQueries : github.com/tannerlinsley/react-query/issues /…

3. Нет, на самом деле, refetch это заставит запросы извлекаться, несмотря ни на что, тогда invalidate как только принудительная выборка, когда запросы не используются. Иногда мы хотим либо того, либо другого. У всех у них есть свое место.

4. БОЛЬШОЕ вам СПАСИБО за ваш последний комментарий, который действительно не очень понятен в их документе!

5. Любопытно, почему недействительность onSettled вместо onSuccess ?

Ответ №2:

Как насчет разделения логики на два разных перехвата? Вместо монолита, подобного useToDos ?

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

 const fetchData = _ => client.get(paths.todos).then(({ data }: any) => data)

export default function useFetchTodo(
  config = {
    refetchOnWindowFocus: false,
    enabled: false
  }
) {
  return useQuery('fetchData', fetchData, config)
}

  

И в вашем перехвате мутации вы можете выполнить повторную выборку вручную, прежде чем createTodo

 import useFetchTodo from './useFetchTodo'
//
const { refetch } = useFetchTodo()

// before createTodo
refetch()

  

Комментарии:

1. Интересная настройка. Мне любопытно, хотя зачем вызывать повторную выборку перед созданием нового элемента? Насколько я понимаю, если запрос не отключен, всякий раз, когда я создаю новый элемент, этот кэш запросов будет обновляться вместе с ним, и мой список элементов в пользовательском интерфейсе будет обновлен. Я что-то упустил? Нужно ли мне вызывать повторную выборку независимо (если не делать оптимистичных ответов)?