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

单个组件中测试多个useQuery仅触发一个查询的问题排查

问题:React Query多查询在测试中仅触发最后一个的解决方案

问题描述

我使用React Query结合json-server模拟API,测试包含9个普通待办和1个固定待办的首页。通过msw模拟两个接口请求,期望验证首页渲染10个待办,但测试时仅最后监听的查询被触发。单独测试单个查询正常,React Query与React Testing Library配置无问题,需解决如何确保渲染组件前两个查询都被调用的问题。

组件代码

export const HomeToDosList = () => {
    const { data: todos, isLoading: isLoadingToDos } = useTodos(page);
    const { data: pinedToDos, isLoading: isLoadingPined } = usePinedTodos();
  
    if (isLoadingToDos) {
      return <div>loading ...</div>;
    }
  
    if (isLoadingPined) {
      return <div>loading ...</div>;
    }
    return (
        <div>
          {/* 注意:此处变量名存在错误 */}
          <ToDoItem initiative={pinedToDo.result} />
          {todos.result.map((todo: ToDo) => (
            <Fragment key={todo.id}>
              <ToDoItem todo={todo} />
            </Fragment>
          ))}
        </div>
    );
};

测试代码

beforeAll(() => {
  getAllToDos.listen();
  getPinedToDos.listen();
});

afterEach(() => {
  getPinedToDos.resetHandlers();
  getAllToDos.resetHandlers();
});

afterAll(() => {
  getPinedToDos.close();
  getAllToDos.close();
});

describe('Home TODOS', () => {
  test('should render 10 todos', async () => {
    render(<HomeToDosList />);
    const todos = await screen.findAllByTestId('todo-card');
    expect(todos.length).toBe(10);
  });
});

解决方案

1. 修正MSW的Handler注册方式

你当前的核心错误是每个MSW Handler单独调用listen(),这会导致后执行的listen()覆盖之前的配置,最终只有最后一个Handler生效。正确做法是创建统一的Server实例,批量注册所有Handler后统一管理:

import { setupServer } from 'msw/node';
import getAllToDos from './path-to-getAllToDos';
import getPinedToDos from './path-to-getPinedToDos';

// 创建统一Server并注册所有Handler
const server = setupServer(getAllToDos, getPinedToDos);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

describe('Home TODOS', () => {
  test('should render 10 todos', async () => {
    render(<HomeToDosList />);
    const todos = await screen.findAllByTestId('todo-card');
    expect(todos.length).toBe(10);
  });
});

2. 修复组件变量错误

组件中误用了未定义的pinedToDo变量,正确命名应为pinedToDos(与usePinedTodos返回的data命名一致),否则固定待办无法渲染:

// 错误写法
<ToDoItem initiative={pinedToDo.result} />

// 正确写法
<ToDoItem initiative={pinedToDos.result} />

3. 优化加载状态判断逻辑

当前组件的加载判断是串行的:先判断普通待办加载状态,返回loading;再判断固定待办加载状态。这会导致如果普通待办先加载完成,组件会提前渲染固定待办的loading,可能干扰查询执行时机。建议合并加载状态判断,确保两个查询都完成后再渲染内容:

// 合并加载状态判断
if (isLoadingToDos || isLoadingPined) {
  return <div>loading ...</div>;
}

补充说明

完成以上修改后,两个查询会同时发起,MSW能正确拦截所有请求,组件也会在两个请求都完成后渲染全部10个待办,测试即可通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 09:55:31