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

调用API刷新MaterialUI Autocomplete选项后Formik表单被重置为初始值

修复方案

根因定位

  • Formik 组件的 initialValues 引用不稳定:如果 initialValues 直接定义在组件内部没有做引用缓存,父组件重渲染时会生成新的对象引用,Formik 默认检测到 initialValues 变化就会将整个表单重置为初始值。你调用异步接口时如果触发了 clubsLoading 等状态更新,会导致父组件重渲染,进而触发该逻辑。
  • FastField 使用了内联的 children 函数:每次重渲染时都会生成新的函数实例,导致 FastField 内部的 Autocomplete 组件卸载后重新挂载,字段值会被重置为初始状态。
  • getClubs 或 fetchClubs 引用不稳定:如果 getClubs 没有用 useCallback 包裹,每次渲染会生成新的实例,连带触发关联组件重渲染。

具体修复步骤

  1. 缓存 Formik 的初始值,保证引用稳定
    使用 useMemo 包裹 initialValues,仅当服务端返回的初始编辑数据变化时才更新引用:
const initialValues = React.useMemo(() => ({
  club: serverInitData.club,
  // 补充其他所有表单字段的初始值
}), [serverInitData])

如果不需要在编辑过程中动态更新初始值,可以直接给 Formik 组件添加 enableReinitialize={false} 属性,强制关闭自动重置表单的逻辑:

<Formik
  initialValues={initialValues}
  enableReinitialize={false}
  // 其他 Formik 配置项
>
  {/* 表单内容 */}
</Formik>
  1. 提取 FastField 的渲染函数并缓存
    把 FastField 内部的内联渲染函数提取出来,用 useCallback 包裹保证引用稳定:
const renderClubAutocomplete = React.useCallback(() => (
  <FormField.AutoComplete
    label="Клуб"
    name="club"
    value={values.club}
    setFieldValue={setFieldValue}
    setTouched={setFieldTouched}
    touched={touched.club}
    errors={errors.club}
    options={clubs}
    disabled={clubsLoading}
    selectionDisabled={clubsLoading}
  />
), [values.club, setFieldValue, setFieldTouched, touched.club, errors.club, clubs, clubsLoading])

修改 FastField 调用方式:

<FastField
  name="club"
  options={clubs}
  optionsLoading={clubsLoading}
  shouldUpdate={(next, prev) =>
    shouldFastFieldRerender(next, prev, getIn)
  }
>
  {renderClubAutocomplete}
</FastField>
  1. 稳定接口函数引用
    确保 getClubs 函数已经用 useCallback 包裹,避免每次渲染生成新的实例,导致 fetchClubs 引用变化触发重渲染。

内容的提问来源于stack exchange,提问作者r.kashigin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 11:45:06