【问题标题】:How to handle multiple queries with React-Query如何使用 React-Query 处理多个查询
【发布时间】:2021-05-31 07:44:05
【问题描述】:

我已经开始使用 React-Query,如果我只需要从数据库中的单个集合中获取数据,它就非常有用。但是,我正在努力寻找一种查询多个集合以在单个组件中使用的好方法。

一个查询(没问题):

const { isLoading, isError, data, error } = useQuery('stuff', fetchStuff)

if (isLoading) {
     return <span>Loading...</span>
   }
 
   if (isError) {
     return <span>Error: {error.message}</span>
   }
 
   return (
     <ul>
       {data.map(stuff => (
         <li key={stuff.id}>{stuff.title}</li>
       ))}
     </ul>
   )
 }

对不同集合的多个查询 (????):

const { isLoading: isLoadingStuff, isError: isErrorStuff, data: stuff, error: errorStuff } = useQuery('stuff', fetchStuff);
const { isLoading: isLoadingThings, isError: isErrorThings, data: Things, error: errorThings } = useQuery('things', fetchThings);
const { isLoading: isLoadingDifferentStuff, isError: isErrorDifferentStuff, data: DifferentStuff, error: errorDifferentStuff } = useQuery('DifferentStuff', fetchDifferentStuff);

const isLoading = isLoadingStuff || isLoadingThings || isLoadingDifferentStuff
const isError = isErrorStuff || isErrorThings || isErrorDifferentStuff
const error = [errorStuff, errorThings, errorDifferentStuff]

if (isLoading) {
     return <span>Loading...</span>
   }
 
if (isError) {
    return (
      <span>
        {error.forEach((e) => (e ? console.log(e) : null))}
        Error: see console!
      </span>
    );
  }
 
   return (
  <>
    <ul>
      {stuff.map((el) => (
        <li key={el.id}>{el.title}</li>
      ))}
    </ul>
    <ul>
      {things.map((el) => (
        <li key={el.id}>{el.title}</li>
      ))}
    </ul>
    <ul>
      {differentStuff.map((el) => (
        <li key={el.id}>{el.title}</li>
      ))}
    </ul>
  </>
);
 }

我确信一定有更好的方法来做到这一点。由于多种原因,我对 React-Query 非常感兴趣,但一个很好的好处是减少样板。但是,这种方法似乎并不比使用 useEffect 和 useState 来管理我的 api 调用好多少。我确实找到了 useQueries 钩子,但它并没有真正让这变得更干净。

有谁知道 React-Query 中是否有一种方法可以进行多个查询并且只返回一个 isLoading、isError 和 error(array?) 响应?或者只是一种更好的方式来处理我丢失的多个查询?

【问题讨论】:

    标签: reactjs react-query


    【解决方案1】:

    我确实找到了 useQueries 钩子,但它并没有真正让这变得更干净。

    useQueries 为您提供一个结果数组,因此您可以映射它们:

    const isLoading = queryResults.some(query => query.isLoading)
    

    如果您有一个触发多个并发请求的组件,那么库可以做的事情就只有这么多来降低复杂性。每个查询都可以有自己的加载状态/错误状态/数据。每个查询都可以有自己的设置,并且可以表现不同。推荐的方法仍然是将其提取到自定义挂钩并从中返回您想要的内容。

    错误处理可以通过使用带有useErrorBoundary 选项的错误边界来简化。为了简化加载体验,您可以尝试suspense(虽然是实验性的),它会为所有查询显示fallback 加载器。

    这种方法似乎并不比使用 useEffect 和 useState 来管理我的 api 调用好多少。

    这忽略了所有优点,例如(除其他外)缓存、后台重新获取、突变、智能失效等。

    【讨论】:

    • 感谢 TkDodo!我对这一切还是很陌生,我不知道 array.some() 方法。我还将研究错误边界。
    【解决方案2】:

    使用依赖查询,您可以按照文档示例进行操作。

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

    Official documentation - Dependent Queries

    【讨论】:

    • 这很漂亮。谢谢!
    【解决方案3】:

    您可以将查询抽象为单独的查询文件,然后为要一起获取的每个数据集合创建自定义挂钩(很可能是呈现单个页面所需的查询集合)

    // ../queries/someQuery.js
    export const useContactInformation = () => {
    
      const { data, isLoading, error } = useQuery(CONTACT_INFORMATION, () => apicall(someparams), {
        enabled: !!user?.id,
      });
    
      return {
        contactInformation: data
        isLoading,
        error,
      };
    };
    

    然后在另一个文件中...

    // ../hooks/somepage.js
    
    export const useSomePageData = () => {
      const { contactInformation, error: contactError, isLoading: contactIsLoading } = useContactInformation();
      const { activityList, error: activityError, completedActivity, isLoading: activityIsLoading } = useActivityList();
    
      # return true, only when all queries are done
      const isLoading = activityIsLoading || contactIsLoading;
      # return true, only when all queries run successfully
      const error = activityError || contactError;
    
      return {
        error,
        isLoading,
        activityList,
      };
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-27
      • 1970-01-01
      • 2021-07-20
      • 1970-01-01
      • 2022-11-17
      • 2013-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多