使用Formik时如何在TextField中显示已有客户数据?
解决方案
问题核心在于三点:customer是数组结构,和Formik表单字段的键值对不匹配;未开启Formik的enableReinitialize导致编辑时数据无法同步到表单;表单组件未正确绑定Formik状态。
1. 构造匹配表单字段的initialValues
把数组格式的customer转换成和表单字段名对应的对象,让Formik能正确映射到输入框:
const initialValues = customer ? { customer_name: customer[1], customer_contact_person: customer[2] } : { customer_name: '', customer_contact_person: '' };
2. 开启Formik的enableReinitialize
编辑用户时customer props会变化,开启该属性能让Formik重新初始化表单值,确保编辑数据实时显示:
<Formik enableReinitialize // 启用该配置 validateOnMount initialValues={initialValues} validationSchema={customerSchema} onSubmit={(values, { resetForm }) => handleSave(values, resetForm)} >
3. 确保TextField正确绑定Formik状态
如果使用Material-UI的TextField,建议用Formik的Field组件包裹,自动绑定状态和校验信息:
// 替换原有Textfield组件 <Field name="customer_name"> {({ field, meta }) => ( <TextField {...field} id={customer[1] ? 'edit_customer_name_field' : 'add_customer_name_field'} label="Customer" error={meta.touched && !!meta.error} helperText={meta.touched && meta.error} /> )} </Field> <Field name="customer_contact_person"> {({ field, meta }) => ( <TextField {...field} id={customer[1] ? 'edit_customer_contact_person' : 'add_customer_contact_person'} label="Contact person" error={meta.touched && !!meta.error} helperText={meta.touched && meta.error} /> )} </Field>
4. 适配handleSave的参数格式
如果原handleSave期望接收数组,需要把Formik返回的对象转成后端需要的数组结构:
// 示例handleSave函数调整 const handleSave = (values, resetForm) => { // 转换为后端要求的数组格式 const customerData = [id, values.customer_name, values.customer_contact_person]; // 调用AWS后端接口逻辑 // await api.updateCustomer(customerData); resetForm(); handleClose(); };
修改后的完整代码
const customerSchema = Yup.object().shape({ customer_name: Yup.string().required('Customer name is required'), customer_contact_person: Yup.string().required('Customer contact name is required'), }) const CustomerDialog = ({ id, open, customer, handleSave, handleDelete, handleClose }) => { console.log('customer: ', customer) const initialValues = customer ? { customer_name: customer[1], customer_contact_person: customer[2] } : { customer_name: '', customer_contact_person: '' }; return ( <Dialog id='customer_dialog' open={open} fullWidth={true} maxWidth='sm' onClose={handleClose}> {customer && ( <> <DialogTitle> {customer[1] ? `Edit ${customer[1]}` : `Add a new customer`} </DialogTitle> <Formik enableReinitialize validateOnMount initialValues={initialValues} validationSchema={customerSchema} onSubmit={(values, { resetForm }) => handleSave(values, resetForm)} > <Form id={customer[1] ? 'edit_customer_form' : 'add_customer_form'}> <DialogContent> <Stack direction='column' justifyContent='center' alignItems='stretch' spacing={2} > <Field name="customer_name"> {({ field, meta }) => ( <TextField {...field} id={customer[1] ? 'edit_customer_name_field' : 'add_customer_name_field'} label="Customer" error={meta.touched && !!meta.error} helperText={meta.touched && meta.error} /> )} </Field> <Field name="customer_contact_person"> {({ field, meta }) => ( <TextField {...field} id={customer[1] ? 'edit_customer_contact_person' : 'add_customer_contact_person'} label="Contact person" error={meta.touched && !!meta.error} helperText={meta.touched && meta.error} /> )} </Field> </Stack> </DialogContent> <DialogActions> {customer[1] ? ( <Button id='customer_dialog_delete_button' size='large' variant='contained' sx={{ mt: 3, mb: 2, mr: 34, alignSelf: 'flex-start' }} fullWidth={false} color='error' onClick={handleDelete} > Delete </Button> ) : null} <ThemeProvider theme={buttonTheme}> <Button id='customer_dialog_cancel_button' size='large' sx={{ mt: 3, mb: 2, alignSelf: 'flex-end' }} fullWidth={false} color='error' onClick={handleClose} > Cancel </Button> </ThemeProvider> <SubmitButton id='customer_dialog_save_button'>Save</SubmitButton> </DialogActions> </Form> </Formik> </> )} </Dialog> ) }
内容的提问来源于stack exchange,提问作者Jukka Koivu
相关产品推荐
相关产品推荐

