โœ๐Ÿป [Code Camp_TIL] 25์ผ์ฐจ: react-hook-form, ์ œ์–ด ์ปดํฌ๋„ŒํŠธ & ๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ, yup

code_Jยท2023๋…„ 4์›” 23์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
31/41
post-thumbnail

ํผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(react-hook-form)


ํผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

์šฐ๋ฆฌ๋Š” ์ง€๊ธˆ๊นŒ์ง€ ๋ชจ๋“  state๋ฅผ ์ง์ ‘ ๋งŒ๋“ค๊ณ , onChange ํ•จ์ˆ˜๋„ ์ผ์ผ์ด ๋งŒ๋“ค์–ด์„œ ๋ฐ”์ธ๋”ฉํ–ˆ๋‹ค. ์ด์ œ ์ด ๋ถ€๋ถ„์„ *ํผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ„ํŽธํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค!

์ฐธ๊ณ ! ํผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๊ฒ€์ฆ์„ ๋Œ€์‹ ํ•ด์ฃผ๋Š” ํผ, state๋ฅผ ๋Œ€์‹ ํ•ด์ฃผ๋Š” ํผ ๋“ฑ ์ข…๋ฅ˜๊ฐ€ ๊ต‰์žฅํžˆ ๋‹ค์–‘ํ•˜๋‹ค. react-form, redux-form, react-hook-form, formik ๋“ฑ์ด ์žˆ๋‹ค.

react-hook-form

ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์™€ ๊ฐ€์žฅ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ณ  ์„ฑ๋Šฅ์ ์œผ๋กœ ์ข‹์€ ํผ์€ react-hook-form์ด๋‹ค!

์šฐ๋ฆฌ๊ฐ€ ์ด์ „์— ์‚ฌ์šฉํ•˜๋˜ onChange๋ฅผ ๋งŒ๋“ค์–ด์„œ setState๋ฅผ ํ•ด์ฃผ๊ณ  ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ state๊ฐ€ ๋ณ€ํ™”ํ•  ๋•Œ๋งˆ๋‹ค ๋ Œ๋”๋ง์ด ์ผ์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„ํšจ์œจ์ ์ด์—ˆ๋‹ค. ๋˜ํ•œ ๋ณ€ํ™”ํ•œ state๋ฅผ ๋ฐ›์•„์„œ ๋ฆฌ๋ Œ๋”๋งํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ต‰์žฅํžˆ ๋Š๋ฆฌ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ react-hook-form์€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ฐ’์„ state์— ๋ฐ˜์˜ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๋“ฑ๋กํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋  ๋•Œ ํ•œ๋ฒˆ์— ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์–ด์„œ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ด๋‹ค.

์ด๋ ‡๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์„ *๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ๋ผ๊ณ  ํ•œ๋‹ค. react-hook-form์€ ๋น„์ œ์–ด์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  ์žˆ๋‹ค.


์ฐธ๊ณ ! ์ œ์–ด ์ปดํฌ๋„ŒํŠธ(controlled component) vs ๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ(uncontrolled component)

์ œ์–ด ์ปดํฌ๋„ŒํŠธ: ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ state๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€๊ฒฝ๋จ(setState ์‚ฌ์šฉ).
๋น„์ œ์–ด ์ปดํฌ๋„ŒํŠธ: ๋“ฑ๋กํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ํ•œ๋ฒˆ์— ๊ฐ’์„ ๋ณ€๊ฒฝ

๊ธฐ๋ณธ์€ ๋น„์ œ์–ด์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋ณต์žกํ•œ ํผ์ด ํ•„์š”ํ•  ๋•Œ ์ œ์–ด์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค!


react-hook-form ์‹ค์Šต


  1. react-hook-form ์„ค์น˜

npm install react-hook-form
yarn add react-hook-form


  1. react-hook-form ์‚ฌ์šฉ
const ReactHookForm = ()=>{
	// react-hook-form ์—์„œ useForm ์ œ๊ณต
	const {register , handleSubmit} = useForm()

	// ๋“ฑ๋กํ•˜๊ธฐ ํ•จ์ˆ˜ -> handleSubmit์ด ์กฐ์ข…ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜ 
	const onClickSubmit = (data)=>{
		console.log(data)
	}

	return(
		<form onSubmit={handleSubmit(onClickSubmit)}>
			<input type="text" {...register("writer")}/>
			<input type="text" {...register("title")}/>
			<input type="text" {...register("contents")}/>
			<button type="reset"> ๋“ฑ๋กํ•˜๊ธฐ </button>
		</form>
	)
}
export default ReactHookForm

useForm์—์„œ register, handleSubmit, form
register : state๋ฅผ ๋“ฑ๋กํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ๊ธฐ๋Šฅ์ด ๋“ค์–ด์žˆ๋‹ค.
handleSubmit : register์— ์ ํžŒ state๋ฅผ ๋“ฑ๋กํ•ด์ฃผ๋Š” ํ•จ์ˆ˜
form: ์‹ค์ œ html์— ์žˆ๋Š” input๋“ค์„ ๋ฌถ์–ด์ฃผ๋Š” ํƒœ๊ทธ


form๊ณผ button

form ํƒœ๊ทธ์—๋Š” input์— ์ ํžŒ ๋‚ด์šฉ์„ ์ „์†กํ•˜๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค.

๋˜ํ•œ button ํƒœ๊ทธ์˜ type์— reset์„ ์ฃผ๊ฒŒ ๋˜๋ฉด ํด๋ฆญ์‹œ์— ํผ ์•ˆ์— ์žˆ๋Š” input ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค. type์˜ ๊ธฐ๋ณธ ๊ฐ’์€ submit์ด๋‹ค. submit์ผ ๊ฒฝ์šฐ, form ํƒœ๊ทธ์— ๋ฐ”์ธ๋”ฉ๋œ submit ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ฒŒ ๋œ๋‹ค.

๋งŒ์•ฝ form ํƒœ๊ทธ ๋‚ด์—์„œ form๊ณผ ์ƒ๊ด€์—†๋Š” ๋ฒ„ํŠผ์„ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋ฉด, type์„ button์œผ๋กœ ์ค˜์•ผ ํ•œ๋‹ค.

form ๋‚ด๋ถ€์˜ button type ๊ฐ„๋‹จ ์ •๋ฆฌ
reset : form ๋‚ด๋ถ€์˜ input ๊ฐ’์ด ๋ชจ๋‘ ์‚ญ์ œ๋จ
submit : form ๋‚ด๋ถ€์˜ input ๊ฐ’์ด ๋ฐฑ์—”๋“œ๋กœ ๋ณด๋‚ด์ง โ†’ ๊ธฐ๋ณธ๊ฐ’
button : ๋‚˜๋งŒ์˜ ๋ฒ„ํŠผ์„ ๋งŒ๋“ค๊ณ  ์‹ถ์„๋•Œ ์‚ฌ์šฉ


์ฃผ์˜! form ํƒœ๊ทธ ๋‚ด์˜ button์˜ ํƒ€์ž…์ด submit์ผ ๊ฒฝ์šฐ, ๋ฒ„ํŠผ์— ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ๋ฐ”์ธ๋”ฉ ํ•  ์‹œ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. form ํƒœ๊ทธ์˜ submit ํ•จ์ˆ˜์™€ ๋ฐ”์ธ๋”ฉ ๋œ ํ•จ์ˆ˜๋ฅผ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ฒ€์ฆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(yup)

์ง€๊ธˆ๊นŒ์ง€๋Š” ํŠน์ • ๋ฐ์ดํ„ฐ๊ฐ€ ์ˆซ์ž์ธ์ง€, ๋ฌธ์ž์ธ์ง€, ์ตœ์†Œ 8์ž๋ฆฌ์ธ์ง€ ๋“ฑ์˜ ๊ฒ€์ฆ์„ ์ง์ ‘ ๋งŒ๋“ค์–ด์•ผ ํ–ˆ๋‹ค.

yup์€ ์ด๋ ‡๊ฒŒ ๋ณต์žกํ•œ ๊ฒ€์ฆ๊ณผ์ •์„ ๋Œ€์‹ ํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.


yup ์‹ค์Šต

yup์€ ๋ณดํ†ต form๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•œ๋‹ค. ๊ทธ๋ž˜์„œ react-hook-form๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด๋ณด์•˜๋‹ค.

  1. react-hook-form๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์„ค์น˜

yarn add @hookform/resolvers yup


  1. yup ๊ด€๋ จ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , resolver์— ์—ฐ๊ฒฐํ•ด์ฃผ๊ธฐ
import * as yup from 'yup'
import {useForm} from 'react-hook-form'
import {yupResolver} from '@hookform/resolvers/yup'

// yup ์—๋Ÿฌ๋ฉ”์„ธ์ง€ ์ƒ์„ฑ -> ์ œ์–ด ์ปดํฌ๋„ŒํŠธ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•จ.
const schema = yup.object().shape({
  
	myWriter : yup.string().email('์ด๋ฉ”์ผ ํ˜•์‹์ด ์ ํ•ฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.').required('ํ•„์ˆ˜ ์ž…๋ ฅ๊ฐ’์ž…๋‹ˆ๋‹ค.')
  
	myPassword : yup.string().min(4,'๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์ตœ์†Œ 4์ž๋ฆฌ ์ด์ƒ์ž…๋‹ˆ๋‹ค.').max(15,'๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์ตœ๋Œ€15์ž๋ฆฌ ์ž…๋‹ˆ๋‹ค.').required('ํ•„์ˆ˜ ์ž…๋ ฅ๊ฐ’ ์ž…๋‹ˆ๋‹ค.') 
})

const ReactHookForm = ()=>{
	//formState์—์„œ ์—๋Ÿฌ๋ฉ”์„ธ์ง€๋“ค์„ ๋ฐ›์•„์˜ด.
	const {register , handleSubmit, formState} = useForm({
		// schema๋Š” ์œ„์—์„œ ๋งŒ๋“ค์–ด ๋‘” schema
		resolver : yupResolver(schema),
		mode : "onChange"
	})

	// ๋“ฑ๋กํ•˜๊ธฐ ํ•จ์ˆ˜ -> handleSubmit์ด ์กฐ์ข…ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜
	const onClickSubmit = (data)=>{
		console.log(data)
	}

	return(
		<form onSubmit={handleSubmit(onClickSubmit)}>
			์ด๋ฉ”์ผ : <input type="text" {...register("myEmail")}/>
// ์šฐ๋ฆฌ๊ฐ€ ์ƒ์„ฑํ•œ yup์˜ ์—๋Ÿฌ๋ฉ”์„ธ์ง€๋Š” ํ•ญ์ƒ errors์— ๋‹ด๊ธฐ๋Š”๋ฐ ์ด ์—๋Ÿฌ๋Š” ์žˆ์„๋•Œ๋„ ์žˆ๊ณ  ์—†์„ ๋•Œ๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜ต์…”๋„ ์ฒด์ด๋‹์„ ๋ถ™์—ฌ์•ผ ํ•จ.
			<div> {formState.errors.myEmail?.message}</div>
			๋น„๋ฐ€๋ฒˆํ˜ธ : <input type="text" {...register("myPassword")}/>
			<div> {formState.errors.myPassword?.message}</div>
			<button styled={{ backgroundColor: formState.isValid ? "yellow" : "" }}> ๋“ฑ๋กํ•˜๊ธฐ </button>
		</form>
	)
}
export default ReactHookForm

์ตœ์ข…์ ์œผ๋กœ ์—๋Ÿฌ๊ฐ€ ์žˆ๋Š”์ง€ ์žˆ๋Š”์ง€ ์—†๋Š”์ง€ ํ™•์ธ ํ›„ ๋ฒ„ํŠผ์„ ํ™œ์„ฑํ™” ํ•˜๋Š” ๊ฒƒ์€ formState์˜ isValid๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

yup์— ์ •๊ทœํ‘œํ˜„์‹ ์ถ”๊ฐ€ํ•˜๊ธฐ
yup.string().matches(/ ์›ํ•˜๋Š” ์ •๊ทœํ‘œํ˜„์‹! /)



profile
Web FE ๊ฐœ๋ฐœ์ž ์ทจ์ค€์ƒ

0๊ฐœ์˜ ๋Œ“๊ธ€