Как получить n зависимых данных с помощью response-query

Мне нужна помощь с библиотекой реагирующих запросов. Я получаю список объектов, а затем для всех, кто мне нужен, получаю дополнительные данные из другой службы. Как мне сделать это с помощью response-queryuseQuery крючок?

Пример 1:

const { data} = useQuery("USERS", fetchUsers);
data.map(user => useQuery(["ACCOUNT", {userId: user.id}], 
                 ({userId}) => fetchAccount(userId)));

Ошибка:

ESLint: React Hook useQueryнельзя вызвать внутри обратного вызова. React Hooks необходимо вызывать в компоненте функции React или в пользовательской функции React Hook. (перехватчики реакции / перехватчики правил)

7 ответов

Это похоже на текущее решение, по крайней мере, для ответа на запрос v3:

       // Get the user
 const { data: user } = useQuery(['user', email], getUserByEmail)
 const userId = user?.id
 
 // Then get the user's projects
 const { isIdle, data: projects } = useQuery(
   ['projects', userId],
   getProjectsByUser,
   {
     // The query will not execute until the userId exists
     enabled: !!userId,
   }
 )

 // isIdle will be `true` until `enabled` is true and the query begins to fetch.
 // It will then go to the `isLoading` stage and hopefully the `isSuccess` stage :)

Из зависимых запросов док .

Я нашел ответ, предоставленный автором response-query:

Из того, что вы описали, похоже, что это классическая фраза "Я хочу использовать перехватчики React в режиме массива", в которой мы все определенно были раньше.

В 99,9% случаев я чувствую, что ответ на это затруднительное положение состоит в том, чтобы отрендерить использование хуков в несколько компонентов и скомпоновать их результаты после рендеринга, но здесь определенно есть крайние случаи и множество компромиссов. Однако это лучшее решение, которое у нас есть на данный момент, поскольку нет отличного способа использовать MapHooks(item => useQuery(item), items). Это было бы действительно здорово, но поверьте мне, я пошел по этому пути, и хотя у меня действительно кое-что работало более или менее, это в конечном итоге усложнило мой код намного больше, чем я ожидал. В настоящее время React Query, скорее всего, не получит ту функцию, о которой вы говорите, поскольку сама библиотека использует хуки, она привязана к той же механике, что и вы, и потребует огромного количества переархивирования, чтобы хотя бы приблизиться к тому, что вы ' повторное описание.Окупаемость инвестиций не окупится и, скорее всего, снизит производительность, размер и сложность API для остальной части библиотеки.

Чтобы решить вашу конкретную проблему на сегодня, я бы предложил три возможных решения:

  1. Ничего страшного, если запрашивается информация о нескольких столбцах, даже если вам нужен только один. Отрегулируйте запоминание / потребление этой информации в столбцах, чтобы обновлять только в том случае, если они новые. Это значительно упростит задачу и, вероятно, позволит вам двигаться вперед быстрее.

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

  3. Создайте свой собственный небольшой "кеш" для хранения списка уже извлеченной информации о столбцах, а затем объедините свою логику извлечения в один запрос. Используйте свой настраиваемый объект кеша, чтобы заполнять слоты в этом массиве, когда данные доступны, а также поддерживать их в актуальном состоянии, очищая кеш так часто, как вы считаете нужным. Я бы рассмотрел это в крайнем случае, так как вы, по сути, начнете управлять своим собственным кешем, а это именно то, что React Query предназначен для вас. Если вы это сделаете, я бы посоветовал взвесить здесь все преимущества, которые вы получаете с React Query. Это может быть крайний случай, когда стратегия кэширования / выборки React Query не подходит, и это нормально.

Надеюсь это поможет!

https://github.com/tannerlinsley/react-query/issues/138

Используйте зависимые запросы, - пока data (users) разрешено, то ваша вторая строка ключа запроса должна быть ложной, пока у вас не появятся пользователи:

// rename `data` to `users`
const { data: users } = useQuery("USERS", fetchUsers);

// `users` causes query key to be falsy until they are loaded
// rename `data` to `accounts`, map `users` id only and pass to pass in as param
const { data: accounts } = useQuery([users && "ACCOUNT", users.map((u) => u.id)], async (key, userIds) => {
  const response = await fetchAccounts(userIds);

  // TODO any mapping?

  return response;
});

https://www.npmjs.com/package/react-query

Я делаю этот код просто для меня, он отлично работает, реагируя на зависимый документ запроса

      const { yokooUser } = useFirebase()
    // load all bookings using react query nad current user email

const {  isError, error, status,  data } = useQuery(
    ['myOrders', yokooUser.email], async () => await axios.get(`http://localhost:5000/booking/${yokooUser.email}`,
        {
            // The query will not execute until the userId exists
            enabled: !!yokooUser.email,
        }
    ))

if (status === 'loading') {
    return <div>Loading...</div>;
}
// error message query
if (isError) {
    return <div>Error: {error.message}</div>;
}
          import { useQuery } from 'react-query';

const fetchData = async (url) => {
  const response = await fetch(url);
  return response.json();
};

const ParentComponent = () => {
  const { data: firstData, refetch: refetchFirst } = useQuery('firstQuery', () => fetchData('/api/first'));

  const { data: secondData, refetch: refetchSecond } = useQuery(
    ['secondQuery', firstData],  // Invalidate on changes to firstData
    () => fetchData(`/api/second/${firstData.id}`),
    {
      enabled: !!firstData,  // Only enable when firstData is available
    }
  );

  // Additional nested queries...

  return (
    <div>
      {/* Render based on firstData and secondData */}
    </div>
  );
};

    

Я начал использовать для этого другую технику, когда я делаю оба вызова из функции «получить». Преимущество заключается в сокрытии сложности API за функцией. Недостатком является менее детальный контроль над компонентом.

Ниже приведен пример (не проверенный), похожий на то, что я обычно делаю.

       const getProjectsByUser = () => {
   // I'm using axios, but you can use fetch or something else.
   const {data} = axios.get("/api/user")
   
   // Let's assume the user endpoint returns a user with an array of projects
   const projectNames = data.user.projects

   const fetchProjects = projecNames.map(name => axios.get(`/api/projects/${name}`)
   
   // I may use Promise.all or Promise.allSettled
   const projResponses = await Promise.all(fetchProjects)

   return projResponses.data;
 }

Единственный код на каком-то компоненте:

       import {getProjectsByUser } from "some path"

 const { data: user } = useQuery(['user', email], getProjectsByUser)
 const userId = user?.id
 

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

      const { data} = useQuery("USERS", fetchUsers);
const {data:fetchAccount} = useQuery('Account , {userId: user.id}] ,fetchAccount))) 

fetchAccount.map((item)=>{
return (
<div key={item.id}>{item.stuffs}</div>
)
}
Другие вопросы по тегам