Formik + Material UI 当我提交表单并尝试更改值时出现错误
Formik + Material UI bug when i submit form and try to change the values
我有这个 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>
const newValues = {...values} - 创建一个新对象 'newValues' 但所有键都引用与 'values' 中的键相同的对象。您需要对 'values' 进行深度克隆。
为此,请使用 lodash:
const newValues = _.cloneDeep(values)
或更脏的方法(一般不推荐):
const newValues = JSON.parse(JSON.stringify(values));
我有这个 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>
const newValues = {...values} - 创建一个新对象 'newValues' 但所有键都引用与 'values' 中的键相同的对象。您需要对 'values' 进行深度克隆。 为此,请使用 lodash:
const newValues = _.cloneDeep(values)
或更脏的方法(一般不推荐):
const newValues = JSON.parse(JSON.stringify(values));