Я создал простую страницу с формой реакции, используя formik и YUP. Поскольку мне нужно загрузить данные для заполнения выпадающих полей перед загрузкой страницы, я вызываю некоторые API, используя библиотеку response-query.
Я заметил, что форма отображается 4 раза до завершения загрузки страницы. Я не очень хорошо знаком с реакцией, поэтому мне хотелось бы узнать, что можно было бы сделать лучше, чтобы улучшить этот код для дальнейшего использования.
import { useFormik } from 'formik'
import React, { useEffect } from 'react'
import { useQuery } from 'react-query'
import { useParams } from 'react-router-dom'
import Button from '../../../components/Button'
import { ImageRounded } from '../../../components/ImageRounded'
import PageHeader from '../../../components/PageHeader'
import PageTitle from '../../../components/PageTitle'
import { formatDate } from '../../../helpers/DateHelpers'
import { hasMedicalRole, hasRole } from '../../../helpers/EnumHelpers'
import useLoader from '../../../hooks/UseLoader'
import { getUserById } from '../../../services/UserService'
import InputMask from 'react-input-mask'
import * as Yup from 'yup';
import { getActiveRoles, getBiologicalSexs, getMedicalRegistryCouncils, getStates } from '../../../services/EnumService.js'
const FormErrorLabel = ({ formik, field }) => {
return formik.touched[field] && formik.errors[field] ? (
<label className="error">{formik.errors[field]}</label>
) : null;
}
const EditUserPage = ({ }) => {
const params = useParams();
const { loading, setLoading } = useLoader();
const { isLoading, error, data } = useQuery('getUserById', () => getUserById(params.id))
const { isLoading: isloadingBiologicalSexs, error: errorBiologicalSexs, data: dataBiologicalSexs } = useQuery('getBiologicalSexs', () => getBiologicalSexs())
const { isLoading: isloadingStates, error: errorStates, data: dataStates } = useQuery('getStates', () => getStates())
const { isLoading: isloadingMedicalRegistryCouncils, error: errorMedicalRegistryCouncils, data: dataMedicalRegistryCouncils } = useQuery('getMedicalRegistryCouncils', () => getMedicalRegistryCouncils())
const { isLoading: isloadingActiveRoles, error: errorActiveRoles, data: dataActiveRoles } = useQuery('getActiveRoles', () => getActiveRoles())
const user = data?.data?.result;
const biologicalSexs = dataBiologicalSexs?.data?.result;
const states = dataStates?.data?.result;
const medicalRegistryCouncils = dataMedicalRegistryCouncils?.data?.result;
const activeRoles = dataActiveRoles?.data?.result;
const formik = useFormik({
enableReinitialize: true,
initialValues: user ? {
...user,
birthdate: formatDate(user.birthdate)
} : {},
validationSchema: Yup.object({
fullName: Yup.string()
.required('É preciso informar o nome'),
login: Yup.string()
.required('É preciso informar o login'),
birthdate: Yup.string()
.test('dateRequired', 'É preciso informar a data de nascimento', (val) => {
if (!val) return false;
return val.replace(/[^0-9]+/g, '').length > 0;
}),
email: Yup.string()
.required('É preciso informar o e-mail')
.email('É preciso informar um e-mail válido'),
documentNumber: Yup.string()
.required('É preciso informar o número do documento'),
}),
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
},
});
useEffect(() => {
setLoading(isLoading || isloadingBiologicalSexs || isloadingStates || isloadingMedicalRegistryCouncils || isloadingActiveRoles);
}, [isLoading, isloadingBiologicalSexs, isloadingStates, isloadingMedicalRegistryCouncils, isloadingActiveRoles]);
if (error) {
return (<h1>Erro: {JSON.stringify(error.message)}</h1>)
}
return (
user && biologicalSexs && biologicalSexs && states && medicalRegistryCouncils && activeRoles &&
<>
<div className="row">
<div className="col-12">
<PageHeader>
<PageTitle icon="fal fa-user" text="Editar usuário" subtext="Edite as informações do usuário no sistema" />
</PageHeader>
</div>
</div>
<form onSubmit={formik.handleSubmit}>
<div className="row mt-3">
<div className="col-2">
<ImageRounded src={user.profilePicture} alt="foto do usuário" title="foto do usuário" />
</div>
</div>
<div className="form-group mt-3">
<div className="pretty p-switch p-fill">
<input name="isActive"
type="checkbox"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.isActive}
checked={formik.values.isActive} />
<div className="state p-primary">
<label> Ativo</label>
</div>
</div>
</div>
<div className="form-group mt-3">
<label>Nome Completo</label>
<input
className="form-control"
name="fullName"
placeholder="Digite um nome"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.fullName} />
<FormErrorLabel formik={formik} field={'fullName'} />
</div>
<div className="form-group mt-3">
<label>Login</label>
<input
className="form-control disable-autofill"
name="login"
placeholder="Digite um nome de login"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.login} />
<FormErrorLabel formik={formik} field={'login'} />
</div>
<div className="form-group mt-3">
<label>Nascimento</label>
<InputMask
className="form-control datepicker"
mask="99/99/9999"
autoComplete="off"
name="birthdate"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.birthdate} />
<FormErrorLabel formik={formik} field={'birthdate'} />
</div>
<div className="form-group mt-3">
<label className="control-label" style={{ display: 'block' }}>Sexo</label>
<select
className="form-control"
name="biologicalSexId"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.biologicalSexId}
>
{Object.keys(biologicalSexs).map(key => {
return (<option key={key} value={key}>{biologicalSexs[key]}</option>)
})}
</select>
<FormErrorLabel formik={formik} field={'biologicalSex'} />
</div>
<div className="form-group mt-3">
<label>Endereço de Email</label>
<input
className="form-control disable-autofill"
name="email"
placeholder="Digite um email"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.email}
/>
<FormErrorLabel formik={formik} field={'email'} />
</div>
<div className="form-group mt-3">
<label>CPF</label>
<InputMask
className="form-control cpf"
mask="999-999-999-99"
autoComplete="off"
name="documentNumber"
placeholder="Digite seu CPF"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.documentNumber} />
<FormErrorLabel formik={formik} field={'documentNumber'} />
</div>
<div className="mt-3">
<label style={{ display: 'block' }}>Perfis de acesso</label>
{Object.keys(activeRoles).map(key => {
return (
<div key={key} className="pretty p-icon p-curve p-pulse">
<input
type="checkbox"
name="roles"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={key}
defaultChecked={hasRole(user.roles, key)} />
<div className="state p-primary">
<i className="icon fas fa-check"></i>
<label>{activeRoles[key]}</label>
</div>
</div>)
})}
</div>
{hasMedicalRole(user.roles) &&
<section className="mt-3">
<div className="row">
<div className="col-md-4">
<div className="form-group">
<label>Registro</label>
<select
className="form-control"
name="medicalRegistryTypeId"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.medicalRegistryTypeId}>
<option >Selecionar registro</option>
{Object.keys(medicalRegistryCouncils).map(key => {
return (<option key={key} value={key}>{medicalRegistryCouncils[key]}</option>)
})}
</select>
<FormErrorLabel formik={formik} field={'medicalRegistryTypeId'} />
</div>
</div>
<div className="col-md-4">
<div className="form-group">
<label>Nº</label>
<input
className="form-control number"
name="medicalRegistryNumber"
placeholder="Nº do documento"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.medicalRegistryNumber} />
<FormErrorLabel formik={formik} field={'medicalRegistryNumber'} />
</div>
</div>
<div className="col-md-4">
<div className="form-group">
<label>Estado emissor</label>
<select
className="form-control"
name="medicalRegistryStateId"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.medicalRegistryStateId}>
{Object.keys(states).map(key => {
return (<option key={key} value={key}>{states[key]}</option>)
})}
</select>
<FormErrorLabel formik={formik} field={'medicalRegistryStateId'} />
</div>
</div>
</div>
<div className="row mt-3">
<div className="col-md-12">
<div className="form-group mt-3">
<div className="pretty p-switch p-fill">
<input name="prescriptionType" type="radio" value="1" />
<div className="state p-primary">
<label> Usar receita padrão</label>
</div>
</div>
<br />
<small className="text-muted">
Essa opção faz com que a área de receituário do prontuário vem a busca de medicamentos padrão do
smzero
</small>
</div>
<div className="form-group mt-3">
<div className="pretty p-switch p-fill">
<input name="prescriptionType" type="radio" value="2" />
<div className="state p-primary">
<label> Usar receita com texto livre</label>
</div>
</div>
<br />
<small className="text-muted">
Essa opção faz com que a área de receituário do prontuário vem com pesquisa de medicamento
</small>
</div>
<div className="form-group mt-3">
<div className="pretty p-switch p-fill">
<input name="prescriptionType" type="radio" value="3" />
<div className="state p-primary">
<label> Usar receita com certificado digital</label>
</div>
</div>
<br />
<small className="text-muted">
Essa opção faz com que a área de receituário do prontuário permite a assinatura digital
</small>
</div>
</div>
</div>
</section>
}
<div className="form-group mt-5">
<Button color="primary" rounded={true}>Cadastrar usuário</Button>
</div>
</form>
</>
)
}
export default EditUserPage
Уэсли Рамос