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

返回404后msw处理器导致react-query持续处于isLoading状态

问题原因与解决方案

核心原因

你的测试失败是因为React Query默认的重试机制:当请求返回404这类错误状态时,React Query会自动重试请求(默认3次),在重试过程中,钩子的isLoading状态会一直保持true,不会立刻切换到isError,导致waitFor里的断言超时失败。

另外还有一个潜在问题:fetch API收到4xx/5xx状态码时不会自动抛出异常,如果你的usePost钩子没有手动处理这种情况,React Query会把404的响应当成成功结果,永远不会进入错误状态。


解决方案

1. 修改usePost钩子,处理错误并禁用重试

在usePost的useQuery配置中禁用重试,同时手动处理fetch的错误状态:

// usePost.js
import { useQuery } from 'react-query';

export default function usePost(postId) {
  return useQuery(
    ['post', postId],
    async () => {
      const res = await fetch(`https://your-wordpress-site.com/wp-json/wp/v2/posts/${postId}`);
      
      // 关键:手动处理非2xx状态码,抛出异常让React Query识别为错误
      if (!res.ok) {
        const errorData = await res.json();
        throw new Error(errorData.message || `Request failed with status ${res.status}`);
      }
      
      return res.json();
    },
    {
      retry: 0, // 禁用自动重试,失败后直接进入错误状态
    }
  );
}

2. 仅在测试中临时禁用重试

如果不想修改钩子的默认行为,可以在测试的QueryClient中全局设置重试配置:

// 测试文件中修改queryClient初始化
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: 0, // 全局禁用重试,仅作用于测试
    },
  },
});

或者针对单个测试的钩子传递配置(如果usePost支持接收额外的useQuery选项):

it('should handle fetch errors', async () => {
  const postId = 'nonexistent-post';

  const { result } = renderHook(() => usePost(postId, { retry: 0 }), {
    wrapper,
  });

  await waitFor(() => {
    expect(result.current.isLoading).toBeFalsy();
    expect(result.current.isError).toBeTruthy();
  });

  expect(result.current.error).toBeInstanceOf(Error);
});

内容的提问来源于stack exchange,提问作者Enrique Moreno Tent

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:28:06