使用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
相关产品推荐
相关产品推荐

