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

使用Formik创建表单:请求数据填充表单编辑失败求助

解决Formik编辑表单填充数据库数据的问题

我懂你碰到的麻烦了——Formik的initialValues只会在组件首次渲染时生效,而你在componentWillMount里做的是异步数据请求,这时候Formik已经用初始的空值完成渲染了,之后setState更新组件state也不会同步到Formik的表单值里。另外,componentWillMount现在已经被React官方废弃,更推荐用componentDidMount来处理异步数据请求。

下面给你几个可行的解决方案:

方案1:用Formik的setFieldValue手动更新字段

先给Formik组件加个ref,等拿到用户数据后,直接调用Formik的方法更新表单字段:

class UserForm extends Component {
  constructor(props) {
    super(props);
    this.formikRef = React.createRef();
    this.state = { firstName: '' };
  }

  componentDidMount() {
    const repository = new Repository();
    repository.getUser((user) => {
      // 可选:更新组件state
      this.setState({ firstName: user.firstName });
      // 关键操作:用Formik的setFieldValue更新表单值
      if (this.formikRef.current) {
        this.formikRef.current.setFieldValue('firstName', user.firstName);
      }
    }, this.props.currentId);
  }

  render() {
    return (
      <Formik
        ref={this.formikRef}
        initialValues={{
          firstName: this.state.firstName, // 初始空值,后续会被覆盖
        }}
        validationSchema={/* 你的表单验证规则 */}
        onSubmit={(values) => {
          // 表单提交逻辑
        }}
      >
        {({ values }) => (
          <Form>
            <Field name="firstName" type="text" />
          </Form>
        )}
      </Formik>
    );
  }
}

方案2:等数据加载完成后再渲染Formik

如果不想手动操作字段,可以先等待数据获取完成,再渲染Formik组件,这样initialValues就能直接用拿到的用户数据:

class UserForm extends Component {
  constructor(props) {
    super(props);
    this.state = { user: null, isLoading: true };
  }

  componentDidMount() {
    const repository = new Repository();
    repository.getUser((user) => {
      this.setState({ user, isLoading: false });
    }, this.props.currentId);
  }

  render() {
    const { isLoading, user } = this.state;
    if (isLoading) {
      return <div>加载中...</div>;
    }

    return (
      <Formik
        initialValues={{
          firstName: user.firstName, // 直接用已获取的用户数据
        }}
        validationSchema={/* 你的表单验证规则 */}
        onSubmit={(values) => {
          // 表单提交逻辑
        }}
      >
        {({ values }) => (
          <Form>
            <Field name="firstName" type="text" />
          </Form>
        )}
      </Formik>
    );
  }
}

方案3:开启Formik的enableReinitialize属性

Formik自带enableReinitialize属性,当initialValues依赖的state变化时,会自动重新初始化表单值。这个方案代码最简洁,不需要额外操作:

class UserForm extends Component {
  constructor(props) {
    super(props);
    this.state = { user: { firstName: '' } };
  }

  componentDidMount() {
    const repository = new Repository();
    repository.getUser((user) => {
      this.setState({ user });
    }, this.props.currentId);
  }

  render() {
    return (
      <Formik
        enableReinitialize={true} // 关键:开启重新初始化
        initialValues={{
          firstName: this.state.user.firstName,
        }}
        validationSchema={/* 你的表单验证规则 */}
        onSubmit={(values) => {
          // 表单提交逻辑
        }}
      >
        {({ values }) => (
          <Form>
            <Field name="firstName" type="text" />
          </Form>
        )}
      </Formik>
    );
  }
}

这三个方案里,我个人更推荐方案3,代码简洁且符合Formik的设计逻辑,不需要额外的ref操作或加载状态判断,Formik会自动帮你同步数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:46:47