当我提交表单并尝试更改值时,Formik + Material UI 错误

Posted

技术标签:

【中文标题】当我提交表单并尝试更改值时,Formik + Material UI 错误【英文标题】:Formik + Material UI bug when i submit form and try to change the values 【发布时间】:2022-01-12 22:40:45 【问题描述】:

我有这个 formik 代码,我有一个 handleSubmit 来获取值并更改其他数据的值:

async function handleSubmit(values) 
  const newValues = ...values;
  newValues.employee_type = newValues.employee_type.id
  newValues.specialties.main = newValues.specialties.main.id
  newValues.specialties.secondary = newValues.specialties.secondary.id
  newValues.specialties.tertiary = newValues.specialties.tertiary.id

  console.log(newValues)

当我尝试更改来自 formik 的值时,屏幕中的输入值也会更改。例如这一行: newValues.employee_type = newValues.employee_type.id默认情况下,employee_type 就像一个带有 id 键的对象一样出现在我面前,我想用它自身内部的 id 替换这个对象。但是当我这样做时,名称为employee_type的输入在屏幕上变为空,任何人都可以帮助我吗?

          initialValues= ...initialValues 
          validationSchema=validator
          onSubmit=handleSubmit
          enableReinitialize
        >
          ( handleBlur, setFieldValue, getFieldProps, resetForm ) => (
            <Form>
              <Box sx= width: "100%" >
                <Grid container spacing=2 sx=>
                  <Grid item xs=4>
                    <FormTextField name="name" label="Nome" />
                  </Grid>
                  <Grid item xs=3>
                    <FormDate
                      name="birthday"
                      label="Data de Nascimento"
                      required=true
                    />
                  </Grid>
                  <Grid item xs=3 alignItems="stretch">
                    <FormSelectField
                      name="genre"
                      label="Gênero"
                      options=genders
                      required
                    />
                  </Grid>
                  <Grid item xs=2 alignItems="stretch">
                    <FormSelectField
                      name="nationality"
                      label="Nacionalidade"
                      options=countries
                      required
                    />
                  </Grid>
                  <Grid item xs=4 alignItems="stretch">
                    <FormTextField name="social_name" label="Nome Social" />
                  </Grid>
                  <Grid item xs=3 alignItems="stretch">
                    <FormTextField
                      name="naturality"
                      label="Naturalidade"
                      required
                    />
                  </Grid>
                  <Grid item xs=3 alignItems="stretch">
                    <FormSelectField
                      name="ethnicity"
                      label="Etnia"
                      options=ethnicity
                      required
                    />
                  </Grid>
                  <Grid item xs=2 alignItems="stretch">
                    <FormSelectField
                      name="marital_status"
                      label="Estado Civil"
                      options=states
                    />
                  </Grid>
                  <Grid item xs=4 alignItems="stretch">
                    <FormTextField
                      name="physic_national"
                      label="CPF"
                      mask="999.999.999-99"
                      required
                    />
                  </Grid>
                  <Grid item xs=4 alignItems="stretch">
                    <FormTextField
                      name="ident_national"
                      label="Registro Geral"
                      required
                    />
                  </Grid>
                  <Grid item xs=4 alignItems="stretch">
                    <FormTextField
                      name="issuing_body"
                      label="Orgão Emissor"
                      required
                    />
                  </Grid>
                </Grid>
                <div
                  style=
                    marginBottom: "20px",
                    marginTop: "20px",
                  
                >
                  <Typography
                    variant="h7"
                    color="secondary"
                    fontWeight="500"
                    sx= marginTop: "20px" 
                  >
                    Dados de Contato
                  </Typography>
                </div>
                <Grid container spacing=2 sx=>
                  <Grid item xs=4 alignItems="stretch">
                    <FormTextField
                      name="contact.email"
                      type="email"
                      label="Email"
                      required
                    />
                  </Grid>
                  <Grid item xs=4 alignItems="stretch">
                    <FormTextField
                      name="contact.phone"
                      label="Telefone"
                      mask="+99 (99) 99999-9999"
                    />
                  </Grid>
                  <Grid item xs=4 alignItems="stretch">
                    <FormTextField name="contact.cell_phone" label="Celular" />
                  </Grid>
                  <br></br>
                  <Grid item xs=2>
                    <FormTextField
                      name="contact.cep"
                      label="CEP"
                      required
                      onBlur=(e) => handleOnBlur(e, handleBlur, setFieldValue)
                      mask="99999-999"
                    />
                  </Grid>
                  <Grid item xs=2>
                    <FormTextField
                      name="contact.address_number"
                      label="Número"
                      required
                      type="number"
                      InputProps= inputProps:  min: 0  
                    />
                  </Grid>
                  <Grid item xs=2>
                    <FormTextField
                      name="contact.street"
                      fullWidth
                      size="small"
                      label="Logradouro"
                      disabled=true
                      InputLabelProps= shrink: true 
                    />
                  </Grid>
                  <Grid item xs=2>
                    <FormTextField
                      name="contact.district"
                      fullWidth
                      size="small"
                      label="Bairro"
                      disabled=true
                      InputLabelProps= shrink: true 
                    />
                  </Grid>
                  <Grid item xs=2>
                    <FormTextField
                      name="contact.county"
                      fullWidth
                      size="small"
                      label="Localidade"
                      disabled=true
                      InputLabelProps= shrink: true 
                    />
                  </Grid>
                  <Grid item xs=2>
                    <FormTextField
                      name="contact.state"
                      fullWidth
                      size="small"
                      label="Estado"
                      disabled=true
                      InputLabelProps= shrink: true 
                    />
                  </Grid>
                </Grid>
                <div
                  style=
                    marginBottom: "20px",
                    display: "flex",
                  
                >
                  <Typography
                    variant="h7"
                    color="secondary"
                    fontWeight="500"
                    sx= marginTop: "20px" 
                  >
                    Dados de Acesso
                  </Typography>
                </div>
                <Grid container spacing=2 sx=>
                  <Grid item xs=4>
                    <FormTextField
                      name="user_login"
                      label="Nome de Acesso"
                      autoComplete="username"
                    />
                  </Grid>
                  <Grid item xs=4>
                    <FormTextField
                      name="pass_login"
                      label="Senha"
                      type="password"
                      autoComplete="new-password"
                    />
                  </Grid>
                  <Grid item xs=4>
                    <FormTextField
                      name="pass_login_confirmation"
                      label="Repita a Senha"
                      type="password"
                      autoComplete="new-password"
                    />
                  </Grid>
                  <Grid item xs=4>
                    /* <FormTextField name="" label="Confirmar Senha" /> */
                  </Grid>
                </Grid>
                <div
                  style=
                    marginBottom: "20px",
                    display: "flex",
                  
                >
                  <Typography variant="h7" color="secondary" fontWeight="500">
                    Dados Profissionais
                  </Typography>
                </div>
                <Grid container spacing=2>
                  <Grid item xs=6>
                    <Grid container spacing=2>
                      <Grid item xs=12>
                        <FormSearchSelectField
                          name="employee_type"
                          options=types
                          label="Tipo do Prestador :"
                          getOptionLabel=(type) =>
                            type.description ? type.description : ""
                          
                          handleChange=(_, value) => 
                            setFieldValue(
                              "council",
                              value && value.council ? value.council.id : ""
                            );
                            setCouncil(
                              (value && value.council.description) || ""
                            );
                            setFieldValue("employee_type", value);
                          
                          isOptionEqualToValue=(type, value) =>
                            type.id === value.id ? true : false
                          
                        />
                      </Grid>
                      <Grid item xs=12>
                        <TextField
                          fullWidth
                          size="small"
                          InputLabelProps=
                            shrink: true,
                          
                          name=""
                          label="Conselho :"
                          multiple
                          InputProps=
                            value: council,
                          
                          disabled
                        ></TextField>
                      </Grid>
                      <Grid item xs=6>
                        <FormTextField
                          name="council_uf"
                          label="UF :"
                          select
                          multiple
                        >
                          ufs.map((item, key) => 
                            return (
                              <MenuItem key=item value=item>
                                item
                              </MenuItem>
                            );
                          )
                        </FormTextField>
                      </Grid>
                      <Grid item xs=6>
                        <FormTextField
                          name="council_ident"
                          label="Número :"
                          type="number"
                          InputProps= inputProps:  min: 0  
                        ></FormTextField>
                      </Grid>
                    </Grid>
                  </Grid>
                  <Grid item xs=6>
                    <Box
                      sx=
                        borderRadius: 1,
                        display: "flex",
                        alignItems: "center",
                        justifyContent: "center",
                      
                    >
                      <Grid container spacing=2>
                        <Grid item xs=12>
                          <FormSearchSelectField
                            name="specialties.main"
                            options=specialties.filter((item) => 
                              let secondary =
                                getFieldProps("specialties").value.secondary;
                              let tertiary =
                                getFieldProps("specialties").value.tertiary;
                              if (secondary && tertiary) 
                                if (
                                  item.id !== secondary.id &&
                                  item.id !== tertiary.id
                                ) 
                                  return item;
                                
                               else if (secondary) 
                                if (item.id !== secondary.id) 
                                  return item;
                                
                               else if (tertiary) 
                                if (item.id !== tertiary.id) 
                                  return item;
                                
                               else 
                                return item;
                              
                            )
                            label="Especialidade Principal :"
                            required
                            getOptionLabel=(specialty) =>
                              specialty.describe ? specialty.describe : ""
                            
                            handleChange=(_, value) => 
                              setDisableOther(false);
                              setFieldValue("specialties.main", value);
                            
                            isOptionEqualToValue=(specialty, value) => 
                              return specialty.id === value.id ? true : false;
                            
                          />
                        </Grid>
                        <Grid item xs=12>
                          <FormSearchSelectField
                            name="specialties.secondary"
                            options=specialties.filter((item) => 
                              let main = getFieldProps("specialties").value.main;
                              let tertiary = getFieldProps("specialties").value.tertiary;
                              if (main && tertiary) 
                                if (
                                  item.id !== main.id &&
                                  item.id !== tertiary.id
                                ) 
                                  return item;
                                
                               else if (main) 
                                if (item.id !== main.id) 
                                  return item;
                                
                               else if (tertiary) 
                                if (item.id !== tertiary.id) 
                                  return item;
                                
                               else 
                                return item;
                              
                            )
                            label="Outras :"
                            getOptionLabel=(specialty) =>
                              specialty.describe ? specialty.describe : ""
                            
                            list=[]
                            handleChange=(_, value) => 
                              setDisableOther(false);
                              setFieldValue("specialties.secondary", value);
                            
                            isOptionEqualToValue=(specialty, value) => 
                              return specialty.id === value.id ? true : false;
                            
                          />
                        </Grid>
                        <Grid item xs=12>
                          <FormSearchSelectField
                            name="specialties.tertiary"
                            options=specialties.filter((item) => 
                              let main = getFieldProps("specialties").value.main;
                              let secondary = getFieldProps("specialties").value.secondary;
                              if (main && secondary) 
                                if (
                                  item.id !== main.id &&
                                  item.id !== secondary.id
                                ) 
                                  return item;
                                
                               else if (main) 
                                if (item.id !== main.id) 
                                  return item;
                                
                               else if (secondary) 
                                if (item.id !== secondary.id) 
                                  return item;
                                
                               else 
                                return item;
                              
                            )
                            label="Outras :"
                            getOptionLabel=(specialty) =>
                              specialty.describe ? specialty.describe : ""
                            
                            list=[]
                            handleChange=(_, value) => 
                              setDisableOther(false);
                              setFieldValue("specialties.tertiary", value);
                            
                            isOptionEqualToValue=(specialty, value) => 
                              return specialty.id === value.id ? true : false;
                            
                          />
                        </Grid>
                      </Grid>
                    </Box>
                  </Grid>
                  <Grid item>
                    loading ? (
                      <Button
                        disabled
                        sx=
                          bgcolor: "rgba(8, 153, 186, 0.1)",
                          color: "white",
                        
                      >
                        <CircularProgress
                          color="primary"
                          size=20
                          sx= mr: 1 
                        />" "
                        Cadastrando...
                      </Button>
                    ) : (
                      <SubmitButton>Cadastrar</SubmitButton>
                    )
                  </Grid>
                </Grid>
              </Box>
            </Form>
          )
        </Formik>

【问题讨论】:

【参考方案1】:

const newValues = ...values - 创建一个新对象“newValues”,但所有键都引用与“values”中的键相同的对象。您需要对“价值观”进行深度克隆。 为此,请使用 lodash:

const newValues = _.cloneDeep(values)

或更脏的方法(一般不推荐):

const newValues = JSON.parse(JSON.stringify(values));

【讨论】:

以上是关于当我提交表单并尝试更改值时,Formik + Material UI 错误的主要内容,如果未能解决你的问题,请参考以下文章

Formik 在空字段上也显示错误

Formik + Yup:如何在提交前立即验证表单?

在 formik 组件之外处理 formik 表单

提交表单时,会话变量会更改值。

防止多步 Formik 表单在重新渲染上一步时重置表单控件输入

Angular:在更改和设置字段值时禁用字段