被迫重新查询元素以触发点击处理程序

Forced to re-query element in order to fire click handler

我有一个测试,我断言我的 API 请求提供了正确的参数。我正在使用 MSW 来模拟 api,并且我为请求处理程序提供了一个间谍:

test("supplies order direction descending if header button is clicked twice", async () => {
    const mockHandler = jest.fn(handler);

    server.use(rest.get(`${config.apiHost}/targets`, mockHandler));

    // First request to /targets happens on render
    render(<Route>{(props) => <TargetList history={props.history} />}</Route>);
    const button = await screen.findByRole("button", { name: "Port" });

    // Second request to /targets happens on button click
    userEvent.click(button);
    await waitFor(() => {
      expect(mockHandler).toHaveBeenCalledTimes(2);
    });
    
    // Third request to /targets SHOULD happen here but doesn't
    userEvent.click(button);
    await waitFor(() => {
      expect(mockHandler).toHaveBeenCalledTimes(3);
      const lastCall = mockHandler.mock.calls[2];
      const requestArg = lastCall[0];
      expect(requestArg.url.searchParams.get("orderby")).toBe("port");
      expect(requestArg.url.searchParams.get("direction")).toBe("descending");
    });
  });

上面的代码不起作用,因为在按钮上第二次触发点击事件似乎什么也没做。但是,如果我重新查询按钮,那么我可以成功触发处理程序:

test("supplies order direction descending if header button is clicked twice", async () => {
    ...
    const button = await screen.findByRole("button", { name: "Port" });

    // Second request to /targets happens on b utton click
    userEvent.click(button);
    await waitFor(() => {
      expect(mockHandler).toHaveBeenCalledTimes(2);
    });
    // Third request to /targets now works!
    const button2 = await screen.findByRole("button", { name: "Port" });
    userEvent.click(button2);
    await waitFor(() => {
      expect(mockHandler).toHaveBeenCalledTimes(3); // SUCCESS!
      ...
    });
  });

为什么我必须重新查询相同的元素?我做错了什么吗?

我没有完整的源代码,但我假设你正在对你的点击事件处理程序做一些事情,这将强制反应再次呈现,在这种情况下,旧元素将不再出现在 DOM 上,并且因此不会调用单击事件处理程序。

P.S:您可以使用 React 生命周期挂钩来确定组件是否为 re-rendered。