【问题标题】:How to fetch n dependent data with react-query如何使用 react-query 获取 n 个依赖数据
【发布时间】:2020-06-01 06:46:38
【问题描述】:

我需要有关 react-query 库的帮助。 我获取一个对象列表,然后为每个我需要从另一个服务获取额外数据的人。我应该如何使用 react-query useQuery hook 做到这一点?

示例 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 函数中调用。 (react-hooks/rules-of-hooks)

【问题讨论】:

    标签: reactjs react-hooks react-query


    【解决方案1】:

    我找到了react-query作者提供的anwser:

    根据您的描述,这似乎是经典的“我想在数组模式下使用 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#issuecomment-589709270

    【讨论】:

      【解决方案2】:

      使用依赖查询,--直到data(用户)被解析,然后你的第二个查询键字符串应该是假的,直到你有用户:

      // 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#dependent-queries

      【讨论】:

      【解决方案3】:

      这看起来至少是 react-query 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 :)
      

      来自dependent queries doc

      【讨论】:

        【解决方案4】:

        我已经开始为此使用另一种技术,我从“get”函数进行两次调用。优点是隐藏了函数背后的 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
         
        

        【讨论】:

          【解决方案5】:

          在 react 查询的文档中,您可以找到并行查询,它解释了您的问题,如果您需要两个数据,您可以执行以下操作

          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>
          )
          }
          

          【讨论】:

            猜你喜欢
            • 2021-01-13
            • 2021-12-05
            • 1970-01-01
            • 1970-01-01
            • 2016-08-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多