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

React-Hook-Form更新默认值后useFieldArray无法渲染动态字段

React-Hook-Form v6.14.1动态字段更新异常问题

使用React-Hook-Form v6.14.1开发动态表单,表单根据组件状态填充数据。初始加载一切正常,但更新状态后,除动态字段外其他数据均能正常显示。

预期行为

  • 初始加载时,WAN 1标签页显示动态字段(WAN 1 VLAN-1),WAN2无动态字段
  • 点击Update Config按钮后,WAN1无动态字段,WAN2显示一个动态字段(WAN 2 VLAN-1)

实际行为

点击按钮后WAN2的动态字段未显示,useFieldArray返回的fields始终为空数组。

已尝试操作

  • 按照官方文档使用reset方法重置表单默认值
  • 为动态字段设置defaultValue
  • 搜索类似问题,但大多聚焦于已填充字段的值而非字段本身的显示

关键代码片段

App.js(状态管理与表单入口)

const [configdata, setConfigdata] = useState(config);
return (
  <div className="App">
    <UpdateConfig onClick={() => setConfigdata(configUpdated)} />
    <Form
      formData={configdata}
      handleFormData={(data) => console.log(data)}
    />
  </div>
);

Form.js(表单容器与Hook初始化)

使用FormProvider传递表单方法,动态渲染WanFields组件,并在formData更新时调用reset:

const methods = useForm({ defaultValues: props.formData });

useEffect(() => {
  methods.reset(props.formData);
}, [props.formData]);

return (
  <FormProvider {...methods}>
    <form
      onSubmit={methods.handleSubmit((data) =>
        props.handleFormData(data)
      )}
    >
      <Tab.Content>
        {props.formData?.intfs?.length &&
          props.formData?.intfs.map((intf, index) => (
            <Tab.Pane key={index} eventKey={`wan${index}-tab`}>
              <WanFields
                key={`wan${index}-fields`}
                intfNo={index}
                portTypeOptions={props.portTypeOptions}
                data={intf}
              />
            </Tab.Pane>
          ))}
      </Tab.Content>
    </form>
  </FormProvider>
);

WanFields.js(动态字段逻辑)

使用useFieldArray管理动态字段,根据watch值控制字段显示:

const methods = useFormContext();
const { errors, control, watch, register } = methods;
const { fields, append, remove } = useFieldArray({
  control,
  keyName: "fieldid",
  name: `intfs[${intfNo}].subIntfs`
});

const watchIntfStatus = watch(`intfs[${intfNo}].enabledStatus`);
const watchIntfType = watch(`intfs[${intfNo}].enabled`);

// 动态字段渲染逻辑
{watchIntfType?.value >= "2" && (
  <>
    <div className="form-group">
      <div className="btn btn-success" onClick={append}>
        Add
      </div>
    </div>
    <div id={`accordion-${intfNo}`}>
      <Accordion>
        {console.log("FIELDS", fields)}
        {/* 问题:更新数据后fields为空数组 */}
        {fields.map((field, index) => (
          <Card key={field.fieldid}>
            <Accordion.Toggle
              as={Card.Header}
              variant="link"
              eventKey={`${index}`}
              style={{ cursor: "pointer" }}
            >
              <h4>
                WAN {parseInt(intfNo) + 1}{" "}
                <span style={{ margin: "0px 5px" }}>
                  <i className="fas fa-angle-right"></i>
                </span>{" "}
                VLAN-{index + 1}
              </h4>
              <div className="card-header-action">
                <button
                  type="button"
                  className="btn btn-danger"
                  onClick={() => remove(index)}
                >
                  Remove
                </button>
              </div>
            </Accordion.Toggle>

            <Accordion.Collapse eventKey={`${index}`}>
              <Card.Body>
                <div className="form-row">
                  <div className="form-group col-12 col-md-6">
                    <label>IP</label>
                    <input
                      type="text"
                      className="form-control"
                      name={`intfs[${intfNo}].subIntfs[${index}].ipAddress`}
                      defaultValue={field?.ipAddress}
                      ref={register()}
                    />
                  </div>
                  <div className="form-group col-12 col-md-6">
                    <label>Subnet</label>
                    <input
                      type="number"
                      className="form-control"
                      min="0"
                      max="30"
                      name={`intfs[${intfNo}].subIntfs[${index}].subnet`}
                      defaultValue={field?.subnet}
                      ref={register()}
                    />
                  </div>
                </div>
              </Card.Body>
            </Accordion.Collapse>
          </Card>
        ))}
      </Accordion>
    </div>
  </>
)}

核心问题:更新状态后,表单默认值已更新,但useFieldArray的fields属性未同步更新,始终为空数组,导致动态字段无法渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:25:40