В настоящее время я создаю многошаговую форму во время процесса адаптации пользователя, поэтому мне нужно централизовать все данные формы в состоянии родительского компонента React.
Мне нужно обновить initialValues с информацией о пользователе, но это асинхронный c процесс.
Я думал о создании ловушки useEffect, вызывающей setState, но, возможно, есть более элегантный способ сделать это ...
Иметь initialValues в качестве одного из Кажется, что зависимости useEffect создают бесконечное число l oop (Maximum update depth exceeded
). Вот почему я обнаружил, что работающим решением было продублировать все initialValues внутри ... ?
Так как же я могу обновлять только указанные c значения из initialValues после получения асинхронной c информации о пользователе?
Вот упрощенная версия реализации:
import React, { useState, useEffect } from 'react'
// Auth0 hook for authentication (via React Context).
import { useAuth0 } from '../../contexts/auth/auth'
import { Formik, Form, Field } from 'formik'
export default () => {
const { user } = useAuth0()
const initialValues = {
profile: {
name: '',
address: '',
// Other properties...
},
personalInfo: {
gender: '',
birthday: '',
// Other properties...
},
}
const [formData, setFormData] = useState(initialValues)
const [step, setStep] = useState(1)
const nextStep = () => setStep((prev) => prev + 1)
useEffect(() => {
const updateInitialValues = (user) => {
if (user) {
const { name = '', gender = '' } = user
const updatedInitialValues = {
profile: {
name: name,
// All other properties duplicated?
},
personalInfo: {
gender: gender,
// All other properties duplicated?
},
}
setFormData(updatedInitialValues)
}
}
updateInitialValues(user)
}, [user, setFormData])
switch (step) {
case 1:
return (
<Formik
enableReinitialize={true}
initialValues={formData}
onSubmit={(values) => {
setFormData(values)
nextStep()
}}
>
<Form>
<Field name="profile.name" type="text" />
<Field name="profile.address" type="text" />
{/* Other fields */}
<button type="submit">Submit</button>
</Form>
</Formik>
)
case 2:
return (
<Formik
enableReinitialize={true}
initialValues={formData}
onSubmit={(values) => {
setFormData(values)
nextStep()
}}
>
<Form>
<Field name="personalInfo.gender" type="text" />
<Field name="personalInfo.birthday" type="text" />
{/* Other fields */}
<button type="submit">Submit</button>
</Form>
</Formik>
)
// Other cases...
default:
return <div>...</div>
}
}