๐ Formik์ผ๋ก input state ์ฝ๊ฒ ๊ด๋ฆฌํ๊ธฐ
์ด์ ๊ธ์์ 2๊ฐ ์ด์์ useState
๋ฅผ ํ๋๋ก ๋ฌถ์ด input
์ ๊ตฌํํ์๋ค. ๊ทธ๋ฐ๋ฐ, input
์ด ํ์ํ ๋๋ง๋ค useState
๋ก ์์ฑํ์ฌ ๊ด๋ฆฌํ๊ณ , ํ์
์ด ์ฌ๋ฌ ๊ฐ์ง์ผ ๋ ๋งค๋ฒ ๊ทธ์ ๋ง๋ handleChange
๋ฅผ ๊ตฌํํ๋๊ฒ์ ์๋นํ ๋ฒ๊ฑฐ๋กญ๋ค๊ณ ์๊ฐํ๋ค. ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค๋ ์ด๋ฏธ ๊ฐ์ ์๊ฐ์ ํ๋์ง, ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ด๋ฏธ ์กด์ฌํ๊ณ ์์๋ค. Formik๊ณผ React Hook Form ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ๋ฐ, ์ค๋์ Formik
์ ๋ํด์ ์์ธํ๊ฒ ์์๋ณด์. Formik
์ React
์์ Form
์ ๊ตฌํํ ๋ ๊ฐ์ฅ ์ฑ๊ฐ์ ์ธ ๊ฐ์ง๋ฅผ ๋์์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
1. ์์ ์ํ ์ํ์์ ๊ฐ ๊ฐ์ ธ์ค๊ธฐ
2. ์ ํจ์ฑ ๊ฒ์ฌ ๋ฐ ์ค๋ฅ ๋ฉ์์ง
3. ์์ ์ ์ถ ์ฒ๋ฆฌ
์์ ๋ชจ๋ ๊ฒฝ์ฐ์ ์ฝ๋๋ฅผ ํ ๊ณณ์ ๋ฐฐ์นํจ์ผ๋ก์จ ํ ์คํธ์ ๋ฆฌํฉํฐ๋ง, ์ถ๋ก ์ ์ฝ๊ฒ ํ ์ ์๋ค๊ณ ๊ณต์๋ฌธ์์๋ ๋์์๋ค. (By colocating all of the above in one place, Formik will keep things organized--making testing, refactoring, and reasoning about your forms a breeze.)
๊ฒฐ๋ก ์ ์ผ๋ก ๋ด๊ฐ Formik
์ ์ฌ์ฉํ๋ฉด์ ๊ฐ์ฅ ํธํ๊ฒ ์๊ฐํ๋ ์ ์ ์ด์ ์ useState
ํ์
์ ๋ฐ๋ผ handleChange
ํจ์๋ฅผ ๋ฐ๋ก ์์ฑํด์ผํ๋ ๋ฒ๊ฑฐ๋ก์์ด ์์๋๋ฐ, Formik
์์ ์ ๊ณตํ๋ handleChange
๋ฅผ ์ฌ์ฉํ๋ฉด ํจ์๋ฅผ ๋ฐ๋ก ๊ตฌํํ์ง ์์๋ ํด๋น ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋ค. ์ถ๊ฐ๋ก handleBlur
, handleSubmit
๊ณผ ๊ฐ์ ํจ์๋ ์์ฒด์ ์ผ๋ก ์ ๊ณตํ๋ ๋งค๋ฒ ํจ์๋ฅผ ์์ฑํ๋ ๊ฒ๋ณด๋ค ์ ์ฒด ์ฝ๋๊ฐ ์ค์ด๋๋ ์๋นํ ์ด์ ์ด ์์๋ค. ๋ํ ์ ํจ์ฑ(Validation)
๊ฒ์ฌ๋ ์งํ ํ ์ ์๋๋ฐ, form
ํ์์ ์ ์ถ ํ ๋ ํ์๋ก ์
๋ ฅํด์ผ ํ๋ input
์ด๋, ๊ตฌ์ฒด์ ์ธ minLength
, maxLength
๊ธ์ ์๋ฅผ ์ ํ ์๋ ์๊ณ , ์ ๊ท ํํ์์ผ๋ก ์ ํจ์ฑ ๊ฒ์ฌ(input
๊ฐ์ด ์ด๋ฉ์ผ ํ์์ธ์ง ์๋์ง)๋ ํ ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ ์
๋ ฅ์ ์๋ฃํ ํ์ ํ๋์ ์ค๋ฅ ์ฌ๋ถ๋ฅผ ํ์ธํ๊ฒ ๋์์ฃผ๋ errors
๊ธฐ๋ฅ, form
์ ๋ง์ก๋์ง ํ์ธํ๋ touched
๊ธฐ๋ฅ ๋ฑ์ด ์๋ค.
์์ Formik
์์๋ ์ ํจ์ฑ(Validation)
๊ฒ์ฌ๋ ํ ์ ์๋ค๊ณ ์ธ๊ธํ๋๋ฐ, Yup
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ๊ฐ์ฒด ์คํค๋ง ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์งํ ํ ์ ์๋ค. ๊ณต์๋ฌธ์์๋ ๋์์๋ฏ์ด ์ ํจ์ฑ๊ฒ์ฌ๋ฅผ ์ํด Yup
์ ๋ฐ๋์ ์ฌ์ฉํด์ผํ๋ ๊ฒ์ ์๋๋ค(Yup is 100% optional.) ํ์ง๋ง, Yup
์ ์ฌ์ฉํ๋ฉด ์งง์ ์ฝ๋๋ก๋ ์ ํํ๊ฒ ์ ํจ์ฑ ๊ฒ์ฌ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋ ์ฅ์ ์ด ์๋ค. ์งง์ ์ฝ๋๋ ๊ฐ๋
์ฑ์ ์ฆ๊ฐ์์ผ์ฃผ๊ณ ์ด๋ ํ์
์ ์์ฐ์ฑ์ ์ฆ๊ฐ์ํค๋ ์์๊ฐ ๋๋ค.
Formik
์ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ ๋ฐฉ๋ฒ์ Getting Started์๋ ๋์ ์์ง๋ง, ๋ด๊ฐ ์ง์ ๋ง์ฃผํ๋ ์ฝ๋์ ์ /ํ ์ํ๋ฅผ ๋ณด๋ฉด์ ์ค๋ช
ํ๋ ๊ฒ์ด ์๋ฌด๋๋ ๊ธฐ์ต์ ์ค๋ ๋จ์๊ฒ ๊ฐ์ ์ฝ๋๋ฅผ ์ผ๋ถ ์์ ํ์ฌ ๊ฐ์ ธ์๋ค. ์๋ ์ฝ๋๋ธ๋ญ์ Formik
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ์ฝ๋์ด๋ค. ์๋ง React
๋ฅผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์๋ค์๊ฒ ์ต์ํ ์ฝ๋์ด์ง ์์๊น ์ถ๋ค.
์ฝ๋๋ฅผ ๋๋ต์ ์ผ๋ก ์ค๋ช
ํ์๋ฉด, userEmail
๊ณผ userName
๋ชจ๋ string
ํ์
์ด๋ผ ํ๋์ useState
์ ๋ฌถ์ด์ ์ ์ธํ๊ณ , personalInfo
, adInfo
๋ชจ๋ boolean
ํ์
์ด๋ผ ๋ง์ฐฌ๊ฐ์ง๋ก ํ๋์ useState
์ ์ ์ธํ๋ค. ๊ทธ๋ฆฌ๊ณ handleInput
์ string
์ด ๋ณํ๋ ๊ฐ์ ์ถ์ ํ๋ ํจ์์ด๊ณ , handlePartTerms
๋ boolean
ํ์
์ด ๋ณํ๋ ๊ฐ์ ์ถ์ ํ๋ ํจ์, handleTotalTerms
๋ boolean
๊ฐ์ ํ๋ฒ์ ๋ชจ๋ ๋ฐ๊ฟ์ฃผ๋ ํจ์์ด๋ค. ํฌ๊ฒ ๋ณด๋ฉด handlePartTerms
์ handleTotalTerms
์ ์ฑ๊ฒฉ์ด ๊ฐ์ ๋ฌถ์ด์ ์ ์ธํ ์๋ ์์ง๋ง ํผ์ ํ๋๋ฅผ ์ง์ ์์ ํ๋ ๊ฒ๊ณผ ๋ ์์ชฝ ๋ ์ด์ด์์ ์์ ํ๋ ๊ฒ์ด ์ฐจ์ด๋ผ๋ ๊ด์ ์์ ๋ณด๋ฉด ๋๋๋ ํธ์ด ์ข์ ๊ฒ ๊ฐ์ ํธ๋ค๋ฌ๋ฅผ ๋ฐ๋ก ์ ์ํ๋ค. ๋ง์ง๋ง์ผ๋ก handleSubmit
์ form
์์ ์ ์ถ ํ ๋ ์คํ๋๋ ํจ์์ด๋ค. ์ง๊ธ ์์ฑํ ์ฝ๋๋ณด๋ค ๋์ฑ ๊น๋ํ๊ฒ ์์ฑํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ฌด๊ถ๋ฌด์งํ์ง๋ง, ํ์ฌ ์ํ์์๋ ํธ๋ค๋ฌ ์ฝ๋๊ฐ ๋ง์ ๊ฐ๋
์ฑ์ด ๋จ์ด์ง๋ค๊ณ ์๊ฐ์ด ๋ ๋ค.
export default function WithoutFormik() {
const [{ userEmail, userName }, setInput] = useState<InputType>({
userEmail: '',
userName: '',
})
const [{ personalInfo, adInfo }, setAgree] = useState<AgreeType>({
personalInfo: false,
adInfo: false,
})
const handleInput = (e: SyntheticEvent) => {
const { id, value } = e.target as HTMLInputElement
setInput((prevState) => ({ ...prevState, [id]: value }))
}
const handlePartTerms = (e: { target: HTMLInputElement }) => {
const { id } = e.target
setAgree((prevState) => ({
...prevState,
[id]: !prevState[id],
}))
}
const handleTotalTerms = (e: { target: HTMLInputElement }) => {
const { checked } = e.target
setAgree(
checked
? {
personalInfo: true,
adInfo: true,
}
: {
personalInfo: false,
adInfo: false,
},
)
}
const handleSubmit = async () => {
await applyServer({
userEmail,
userName,
personalInfo,
adInfo
})
}
return(
<>
<Template />
</>
)
}
๊ทธ๋ ๋ค๋ฉด, Formik
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ฝ๋๋ ์ด๋ป๊ฒ ์์ฑํ๋์ง ์ดํด๋ณด์. ํ๋จ ์ฝ๋ ๋ธ๋ก์ ๋ณด๋ฉด ํ๋์ ๋ด๋ ์ฝ๋๊ฐ ๋ง์ด ์ค์ด๋ ๊ฒ์ด ๋ณด์ด์ง ์๋๊ฐ? ๋ํ, ๊ตฐ๋ฐ๊ตฐ๋ฐ ํฉ์ด์ ธ ์๋ ์ฝ๋๊ฐ ํ ๊ณณ์ ๋ชจ์ฌ ์ ์ธ๋์ด์์ผ๋ ๊ฐ๋
์ฑ๋ ๋ง์ด ์ข์์ก๋ค. ๊ทธ๋ฆฌ๊ณ ์ด์ ์ฝ๋์์๋ ์ ํจ์ฑ ๊ฒ์ฌ ์ฝ๋๋ฅผ ๋ฃ์ง ์์๋๋ฐ, ์ฌ๊ธฐ์ validationSchema
๋ผ๋ ์ ํจ์ฑ ๊ฒ์ฌ ์ฝ๋๊น์ง ๊ฐ์ด ๋ฃ์๋ค.(Yup
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ฌ์ฉํ๋ค.)
Formik
์ ์ฅ์ ์ handleChange
ํธ๋ค๋ฌ๋ฅผ ํ์
๋ณ(string
, boolean
)๋ก ๋ฐ๋ก ์ ์ํ์ง ์์๋ handleChange
ํ๋๋ก ์ฌ์ฌ์ฉํ ์ ์๋ค๋ ์ ๊ณผ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์งํํ ๋ isValid
๋ฅผ ์ฌ์ฉํ์ฌ ์ ํจ์ฑ ๊ฒ์ฌ๊ฐ ๋ชจ๋ ํต๊ณผํ์ง ์์ผ๋ฉด(์ด๋๋ isValid
๊ฐ false
๊ฐ ๋๋ค.) button
์ disabled
๋ก ๋ง๋ค ์ ์๋ค. ์ถ๊ฐ๋ก input
์ ์ต์ / ์ต๋ ๊ธธ์ด๊น์ง ์ ์ธํ์ฌ ํด๋น ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ฉด ์๋ฌ ๋ฉ์์ง๋ ๋์ธ ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ errors
๊ฐ์ฒด๋ก validationSchema
์ ์ ํจ์ฑ ๊ฒ์ฌ๊ฐ ํต๊ณผํ์ง ์์์ ๋ ํด๋น ๋ฉ์์ง๋ ๋ณด์ฌ์ค ์ ์๋ค. ๋ง์ง๋ง์ผ๋ก form
์ ์ ์ถํ๊ณ ์๋ต์ด ์ค๊ธฐ ์ ๊น์ง button
์ disabled
๋ก ๋ง๋๋ isSubmitting
๊น์ง ๋ณ๋์ ๋ก์ง ์ ์ธ ์์ด ์ฌ์ฉํ ์ ์๋ ์ ์ด ๋ง์์ ๋ค์๋ค.
export default function WithFormik() {
const {
values,
errors,
isValid,
isSubmitting,
setValues,
handleChange,
handleSubmit,
} = useFormik({
initialValues: {
userEmail: '',
userName: '',
personalInfo: false,
adInfo: false,
},
validationSchema: Yup.object({
userEmail: Yup.string()
.email('์ด๋ฉ์ผ ํ์์ด ์๋๋๋ค.')
.required('์ด๋ฉ์ผ์ ์
๋ ฅํด ์ฃผ์ธ์.'),
userName: Yup.string().required('๋๋ค์์ ์
๋ ฅํด ์ฃผ์ธ์.'),
personalInfo: Yup.bool().isTrue('๊ฐ์ธ์ ๋ณด ์์ง์ ๋์ํด์ฃผ์ธ์.'),
adInfo: Yup.bool().isTrue('๊ด๊ณ ์ฑ ์ ๋ณด ์์ ์ ๋์ํด์ฃผ์ธ์.'),
}),
onSubmit: async ({email, nickname, personalInfo, adInfo}) => {
await applyServer({
email,
nickname,
personalInfo,
adInfo,
})
},
})
const { userEmail, userName, personalInfo, adInfo } = values
const isActive = isValid && !isSubmitting
const allTermsHandleChange = () => {
void setValues(
checkedAllTerms
? {
userEmail,
userName,
personalInfo: false,
adInfo: false,
}
: {
userEmail,
userName,
personalInfo: true,
adInfo: true,
},
)
}
return(
<>
<Template />
</>
)
}
์ด๋ฐ์๋ React Context
์ ๋์ผํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅํ useFormikContext
, form
ํ๊ทธ์ handleSubmit
์ ์ฌ์ฉํ์ง ์์๋ ๋๋ <Form />
, input
ํ๊ทธ์ handleChange
๋ฅผ ์ฌ์ฉํ์ง ์์๋ ๋๋ <Field />
ํ๊ทธ ๋ฑ ๋ค์ํ ๊ธฐ๋ฅ์ด ์๋ค.
๊ทธ๋ฌ๋, Formik
์๋ ๋จ์ ์ ์กด์ฌํ๋ค. ์ ํด์ง ํ๊ทธ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ์ , ๋ณต์กํ form
์ ๋ค๋ฃจ๊ธฐ๊ฐ ์ด๋ ต๊ณ ๋ด๊ฐ ์ํ๋ ๋๋ก ์ปค์คํ
ํ๊ธฐ๊ฐ ์ผ๋ฐ์ ์ธ form
์ ๋นํด ์กฐ๊ธ์ ๋ถํธํ๋ค๋ ์ . ๊ทธ๋ฌ๋, ์ด๋ฐ ๋จ์ ์ ๊ทน๋ณตํ ์ ์๋ ์ฅ์ (input
๋ก์ง์ ์ผ์ผ์ด ๊ตฌํํ๊ธฐ ๊ท์ฐฎ๊ฑฐ๋ ํ์
ํ ๋ ๋ฑ)์ด ๋ ๋ง๊ธฐ ๋๋ฌธ์ ํ ๋ฒ์ฏค Formik
์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถํ๋ฉฐ ์ด ๊ธ์ ๋ง์น๋ค.
Reference
๋๊ธ