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

React Testing Library测试useForm表单输入后错误提示不消失问题

你遇到的问题核心有两个:

  1. React Hook Form 默认的校验触发时机为onSubmit,也就是只有提交表单时才会执行校验,你修改输入框值后不会自动触发重新校验,因此错误提示不会消失。
  2. 测试代码的查询逻辑和断言逻辑存在问题,导致测试无法匹配预期行为。

第一步:调整React Hook Form配置

在初始化useForm时增加mode参数,指定校验触发时机为输入值变化时触发:

const {
  register,
  handleSubmit,
  formState: { errors },
} = useForm({ 
  resolver: yupResolver(schema),
  mode: 'onChange' // 输入值变化时自动重新校验
});

如果不想全局修改校验触发时机,也可以在修改输入值后手动调用trigger()方法触发校验。


第二步:修正测试代码

测试代码存在3个需要调整的点:

  • 不需要手动用act()包裹fireEvent,React Testing Library的事件触发方法已经内部处理了act逻辑,额外包裹反而可能导致状态更新异常
  • 提交表单后需要先等待错误提示渲染完成,再修改输入值
  • 修改输入值后不能用findAllByTestId查询错误元素,如果错误已经消失,该异步查询会超时失败,应该用queryAllByTestId,查询不到对应元素会返回空数组,不会抛出异常

修改后的测试代码如下:

test("Correct input does not give error anymore", async () => {
  render(
    <ThemeProvider theme={theme}>
      <LoginForm />
    </ThemeProvider>
  );
  const button = screen.getByDisplayValue(/Login/i);
  // 点击提交触发校验
  fireEvent.click(button);
  // 等待错误提示渲染完成
  await screen.findAllByTestId("error");

  const usernameInput = screen.getByLabelText(/username:/i);
  const passwordInput = screen.getByLabelText(/password:/i);
  
  // 输入合法值,自动触发校验
  fireEvent.change(usernameInput, { target: { value: "test123" } });
  fireEvent.change(passwordInput, { target: { value: "123456" } });

  // 校验输入值正确
  expect(usernameInput.value).toBe("test123");
  expect(passwordInput.value).toBe("123456");
  // 校验错误提示已经全部消失
  expect(screen.queryAllByTestId("error")).toHaveLength(0);
});

额外注意点

你在password输入框的register参数中额外写了{ required: true },这和Yup校验规则重复,建议删除避免冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 21:39:01