最近写了一个项目,是通过函数条件化渲染特定内容,其中每一种特定内容都包含一个表单

源码部分如下(源码太长,只截取必要部分)

// 题目类型展示
const ShowQuestionType = () => {
  switch (type) {
    case 1: case 2:
      return (
        <div>
          {/* 第1个Form表单 */}
          <Form form={form} onValuesChange={handleFormChange}>
            <div className={Style.configSearch}>
              <div className={Style.selectDiv}>
                <Form.Item name="departmentList">
                  {/* 表单内容1 */}
                </Form.Item>
              </div>
              <div className={Style.selectDiv}>
                <div className={Style.selectTitle}>参与角色: </div>
                <Form.Item name="roleList">
                  {/* 表单内容2 */}
                </Form.Item>
              </div>
            </div>
          </Form>
        </div>
    );
    case 3:
    return (
    <div>
      <div className={Style.chartMain3}>
        {/* 第2个Form表单 */}
        <Form form={form} onValuesChange={handleFormChange}>
          <div className={Style.configSearch}>
            <div className={Style.selectDiv}>
              <Form.Item name="departmentList">
                {/* 表单内容5 */}
              </Form.Item>
            </div>
            <div className={Style.selectDiv}>
              <div className={Style.selectTitle}>参与角色: </div>
              <Form.Item name="roleList">
                {/* 表单内容6 */}
              </Form.Item>
            </div>
          </div>
        </Form>
      </div>
    </div>
    );
    default:
    return <></>;
  }
};

这里是通过switch,条件渲染指定的表单,其中第一次写每一个大的Form都用的

 <Form form={form} onValuesChange={handleFormChange}>

但是之后我们发现,两个表单中有一些组件是一样的,Form.Item的name也是一样的,这样的话会导致不同的Form中的相同name的Form.Item会互相冲突

那么之后我将所有的Form.Item的name都进行了区分,使他们每一个都唯一的,这样有个缺点是,在handleFormChange函数中得重新定义不同的name,非常麻烦,但还是先改吧

本以为完事大吉,但是发现执行下面这个函数的时候

    form.resetFields()

会导致两个表单都刷新重置

这是肯定的,因为我两个Form都是定义的

 const [form] = Form.useForm();
<Form form={form} onValuesChange={handleFormChange}>
  // 第一个表单的内容
<Form form={form} onValuesChange={handleFormChange}>
  // 第二个表单的内容

都用的form={form},那么我执行form.resetFields(),两个表单都会重置也就情理之中了

那么我就将两个Form的命名区分

 const [form] = Form.useForm();
 const [forms] = Form.useForm();
<Form form={form} onValuesChange={handleFormChange}>
  // 第一个表单的内容
<Form form={forms} onValuesChange={handleFormChange}>
  // 第二个表单的内容

那么我就想,反正每个Form都单独命名了,那我每个Form.Item的name不需要分的那么细,handleFormChange函数中也不需要区分那么多不同的name了,于是我又将每个Form.item改了回来

// 题目类型展示
const ShowQuestionType = () => {
  switch (type) {
    case 1: case 2:
      return (
        <div>
          {/* 第1个Form表单 */}
          <Form form={form} onValuesChange={handleFormChange}>
            <div className={Style.configSearch}>
              <div className={Style.selectDiv}>
                <Form.Item name="departmentList">
                  {/* 表单内容1 */}
                </Form.Item>
              </div>
              <div className={Style.selectDiv}>
                <div className={Style.selectTitle}>参与角色: </div>
                <Form.Item name="roleList">
                  {/* 表单内容2 */}
                </Form.Item>
              </div>
            </div>
          </Form>
        </div>
    );
    case 3:
    return (
    <div>
      <div className={Style.chartMain3}>
        {/* 第2个Form表单 */}
        <Form form={forms} onValuesChange={handleFormChange}>
          <div className={Style.configSearch}>
            <div className={Style.selectDiv}>
              <Form.Item name="departmentList">
                {/* 表单内容5 */}
              </Form.Item>
            </div>
            <div className={Style.selectDiv}>
              <div className={Style.selectTitle}>参与角色: </div>
              <Form.Item name="roleList">
                {/* 表单内容6 */}
              </Form.Item>
            </div>
          </div>
        </Form>
      </div>
    </div>
    );
    default:
    return <></>;
  }
};

之后我发现一个很神奇的事情,就算是给每个Form单独命名了form={form},但是如果Form.Item一样,还是会冲突

(表单Item的name一样,但是Form的引用不一样)

查了一下,这是因为antd表单无论有多少个Form,实际上只会创建一个form实例,在这个实例中会绑定name,所以如果多表单的Form.Item,需要严格把不同的name给区分开,防止冲突

 但是对于每一个form的api,因为我们采用的是form.resetFields()和forms.resetFields(),是antd通过form这个api绑定的,不会冲突

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐