You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Query重复处理isLoading/error的替代方案咨询

解决React Query重复状态判断的几种方案

1. 封装通用状态处理组件

把loading、error、空数据的UI逻辑抽成可复用组件,业务组件只需传入查询结果和正常渲染内容:

// QueryStatusWrapper.jsx
import React from 'react';

export function QueryStatusWrapper({ 
  queryResult, 
  emptyText = '暂无数据', 
  loadingText = '加载中...', 
  errorText = '加载失败', 
  children 
}) {
  if (queryResult.isLoading) {
    return <div>{loadingText}</div>;
  }

  if (queryResult.isError) {
    return <div>{errorText}</div>;
  }

  if (!queryResult.data) {
    return <div>{emptyText}</div>;
  }

  return children;
}

业务组件使用示例:

import { useQuery } from "@tanstack/react-query";
import { fetchAllUsers } from "./useFetchUsers";
import { QueryStatusWrapper } from './QueryStatusWrapper';

const TestComponent = () => {
  const queryResult = useQuery({
    queryKey: ["Users"],
    queryFn: fetchAllUsers,
  });

  return (
    <QueryStatusWrapper queryResult={queryResult}>
      <div>{queryResult.data}</div>
    </QueryStatusWrapper>
  );
};

export default TestComponent;

后续要统一修改loading样式、文案时,直接改Wrapper组件即可,不用逐个业务组件调整。

2. 封装自定义Hook

把useQuery调用和状态判断逻辑封装成自定义Hook,返回处理后的状态字段,简化业务组件代码:

// useCustomQuery.js
import { useQuery } from "@tanstack/react-query";

export function useCustomQuery(options) {
  const queryResult = useQuery(options);

  return {
    ...queryResult,
    // 新增isEmpty字段,避免重复判断!data
    isEmpty: !queryResult.isLoading && !queryResult.isError && !queryResult.data,
  };
}

业务组件使用示例:

import { useCustomQuery } from "./useCustomQuery";
import { fetchAllUsers } from "./useFetchUsers";

const TestComponent = () => {
  const { data, isLoading, isError, isEmpty } = useCustomQuery({
    queryKey: ["Users"],
    queryFn: fetchAllUsers,
  });

  if (isLoading) return <div>加载中...</div>;
  if (isError) return <div>加载失败</div>;
  if (isEmpty) return <div>暂无数据</div>;

  return <div>{data}</div>;
};

3. 利用React Query内置状态解构

React Query本身提供了isLoading、isError、isSuccess等组合状态,直接解构这些字段能大幅简化代码:

import { useQuery } from "@tanstack/react-query";
import { fetchAllUsers } from "./useFetchUsers";

const TestComponent = () => {
  const { isLoading, isError, data } = useQuery({
    queryKey: ["Users"],
    queryFn: fetchAllUsers,
  });

  if (isLoading) return <div>加载中...</div>;
  if (isError) return <div>加载失败</div>;
  if (!data) return <div>暂无数据</div>;

  return <div>{data}</div>;
};

相比原写法,解构后代码更简洁,可读性也更高。

4. 结合Suspense与Error Boundary(React 18+)

如果使用React 18+,可以开启React Query的suspense: true,配合Suspense组件和Error Boundary集中处理加载、错误状态,业务组件无需写状态判断:

首先在全局配置开启suspense:

// App.jsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Suspense } from 'react';
import ErrorBoundary from './ErrorBoundary';
import TestComponent from './TestComponent';

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      suspense: true,
    },
  },
});

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <ErrorBoundary fallback={<div>加载失败</div>}>
        <Suspense fallback={<div>加载中...</div>}>
          <TestComponent />
        </Suspense>
      </ErrorBoundary>
    </QueryClientProvider>
  );
}

业务组件直接使用数据:

import { useQuery } from "@tanstack/react-query";
import { fetchAllUsers } from "./useFetchUsers";

const TestComponent = () => {
  const { data } = useQuery({
    queryKey: ["Users"],
    queryFn: fetchAllUsers,
  });

  // 空数据可在fetch函数返回默认值(比如空数组),避免此处判断
  if (!data) return <div>暂无数据</div>;

  return <div>{data}</div>;
};

该方案将状态处理集中在顶层,业务组件只关注正常渲染逻辑,但需要额外实现Error Boundary组件。

内容的提问来源于stack exchange,提问作者Zach philipp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 00:47:32