React Query – использовать ответ от выборки списка на setQueryData для каждого элемента?

Я получаю список элементов для отображения на странице списка — назовем их Todos. Извлечение осуществляется с помощью специального хука реагирования, который кэширует ответ под ключом запроса ['todo-list']. Когда я получаю список, я получаю все данные для каждого дела в ответе. Затем я визуализирую список, сопоставляя ответ с компонентом <Todo>, передавая элемент в качестве реквизита.

Проблема, с которой я столкнулся, заключается в том, что эти элементы отображаются в нескольких разных местах, и в каждом месте используется другой ключ запроса. Итак, там, где у меня есть ['todo-list'], у меня также есть ['my-todo-list'], ['all-todo-list'] и т. д. Эти элементы Todo могут быть «завершены», что запускает вызов мутации на серверной части, но оптимистично обновляет (через setQueryData) отдельный элемент, чтобы пользовательский интерфейс отражал изменения. немедленно, не дожидаясь разрешения мутации и повторной выборки запроса списка. Вносить такие оптимистичные обновления в несколько списков задач довольно сложно и кажется неэффективным.

Мой вопрос: имеет ли смысл использовать ответ любого запроса списка дел на setQueryData для отдельных элементов? Например, setQueryData(['todo', todo.id], todo). Тогда любые дочерние компоненты, которым необходимо визуализировать эти данные, смогут просто получить объект Todo из кеша реагирующих запросов, при этом в качестве реквизита будет передано только поле id.

В любом случае это считается антипаттерном или плохой практикой?

Вот базовый пример запроса todo-list:

// custom react-query hook
export const useTodos = () => {
  const todoQuery = useQuery(
    ['todo-list'],
    () => {
      return fetchTodos()
    }
  )

  // Set the todo data in the cache
  const queryClient = useQueryClient()
  todoQuery.data?.todos?.forEach((todo) => {
    queryClient.setQueryData(['todo', todo.id], todo)
  })

  return todoQuery
}

Это очень простой пример использования компонента Todo:

// Todo component
function Todo({id}) {
  const {data, isLoading} = useTodoById(id)
  if (isLoading) {
    return <p>Loading...</p>
  }

  return (
    <h1 className = "todo">{todo.title}</h1>
  )
}

export default Todo

Также стоит отметить, что крючок useTodoById также является настраиваемым хуком реагирования на запросы, который извлекает одно задание по его идентификатору — значение кэшируется под ключом запроса ['todo', todo.id]. Есть набор staleTime на 10 минут.

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

Ответы 1

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

То, что вы предлагаете, вовсе не плохая практика, на самом деле она упоминается в блоге TkDodo (мантейнер реагирования на запросы). Вы можете сделать это на основе push или pull, оба имеют плюсы и минусы, которые описаны в блоге. Единственная плохая практика, которую я наблюдаю, - это ваши ключи запроса. Часто рекомендуется использовать такие вещи, как ['todos', 'lists'] и ['todos', 'detail', 1], чтобы вы могли воспользоваться invalidateQuery частичным совпадением. Я бы порекомендовал проверить сообщение в блоге об эффективных ключах запроса

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

Jester2007 25.06.2024 16:23

Конечно, если вы назвали свой queryKeys, как в примере, который я упоминаю, и вы хотите обновить список задач по идентификатору 1 после того, как вы сделали PATCH или PUT, вы можете вызвать invalidateQueries({queryKey: ['todos', 'detail', 1]), что сделает недействительным только этот конкретный запрос, но если вы хотите сделать недействительными все запросы которые связаны с todos, которые вы можете вызвать invalidateQueries({queryKey: 'todos'}), и они должны совпадать со всеми ключами запроса, в массиве которых есть задачи. Это простое соглашение об именах клавиш, дополнительную информацию вы можете найти в блоге, на который я дал ссылку.

Gerardo Sabetta 25.06.2024 20:06

Понял, это имеет смысл. Спасибо! Итак, с помощью этого шаблона (будь то pull или push) мы устанавливаем данные для подробных ключей запроса - например. ['todos', 'detail', 1]. Но как вы думаете, как лучше всего управлять устаревшим временем для этих элементов? Например, я получаю список и устанавливаю initialData. Компоненты рендеринга используют ключ запроса детализации для получения initialData. Но когда срок действия staleTime истечет, вы получите новый запрос для каждого из предметов. Например, на странице со списком, содержащей сотни элементов, это кажется немного тяжелым. Такова природа этого или есть более эффективный способ управления кешем?

Jester2007 27.06.2024 21:56

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

Как установить новое значение для «Сигнала», который вызывается из «Эффекта»?
Как я могу вывести типы аргументов нескольких функций в TypeScript
Сопоставьте значения из NgForm с моделью машинописного текста, определенной в Angular
Могу ли я использовать файлы ts точно так же, как я использую файлы js?
Проблема вывода типа с массивом универсальных объектов конфигурации с разными внутренними типами, которые зависят от другого внутреннего свойства
Почему добавление круглых скобок удаляет «только для чтения [x: число]: число;» из этого типа?
Введите 'строка | логическое значение не может быть назначено для ввода «никогда» в машинописном тексте
Как добавить динамические метаданные на страницу [slug] в маршрутизаторе приложений next.js
Программно переключить свойство, нулевое или необязательное, на обязательное в Zod
Кортеж, который принимает только одно вхождение определенного типа