๐ŸŒฟ

React Hook Form์—์„œ useController vs Controller

controlํ•œ input์„ ๊ด€๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์ด ๋น„์Šทํ•œ useController๊ณผ Controller ์ค‘ ๋ญ˜ ์“ฐ๋ฉด ์ข‹์„ ์ง€์— ๋Œ€ํ•œ ์ƒ๊ฐ

2024.03.11

ํ•ด๋‹น ๊ธ€์€ ํ”„๋กœ์ ํŠธ ๊ฐœ๋ฐœ ์ค‘ ์ปจ๋ฒค์…˜ ๋…ผ์˜๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ์ž๋ฃŒ๋ผ ์กด๋Œ“๋ง๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

react-hook-form์—์„œ Input์€ ๊ธฐ๋ณธ์ ์œผ๋กœ unControlledํ•ฉ๋‹ˆ๋‹ค. (https://legacy.reactjs.org/docs/uncontrolled-components.html)

register ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ref๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์€ ํผ์ด๋‚˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ input์˜ ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ input์— ํƒ€์ดํ•‘ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ฆฌ๋ Œ๋”๋ง์˜ ์–‘์„ ์ค„์ž…๋‹ˆ๋‹ค.

react-hook-form์—์„œ Input์€ ๊ธฐ๋ณธ์ ์œผ๋กœ unControlledํ•ฉ๋‹ˆ๋‹ค. (https://legacy.reactjs.org/docs/uncontrolled-components.html)

register ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ref๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์€ ํผ์ด๋‚˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ input์˜ ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ input์— ํƒ€์ดํ•‘ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ฆฌ๋ Œ๋”๋ง์˜ ์–‘์„ ์ค„์ž…๋‹ˆ๋‹ค.

Controller๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ๋ฆฌ๋ Œ๋”๋ง ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ๋ Œ๋”๋ง์˜ ์–‘์„ ์ค„์ž…๋‹ˆ๋‹ค.

๊ฐœ์ธ์ ์œผ๋กœ๋Š” Controlled Input์€ Input์˜ Rerender์„ ์ผ์œผํ‚ค๊ธฐ ๋•Œ๋ฌธ์— ์›ฌ๋งŒํ•˜๋ฉด register๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ๊ฐ€๋” Controlled Input์„ ์‚ฌ์šฉํ•  ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. (ref๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์„ ๋•Œ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ input์„ ์‚ฌ์šฉํ•  ๋•Œ ๋“ฑ๋“ฑ... )

์ € ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” input ์ปดํฌ๋„ŒํŠธ์˜ value ์ƒํƒœ์— ์˜์กดํ•˜๋Š” ๊ฐ’๋“ค์ด ์—ฌ๋Ÿฌ ๊ตฐ๋ฐ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ์—, input์˜ ๊ฐ’์— ์˜์กดํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ถ€๋ถ„๊นŒ์ง€ ๋งค๋ฒˆ ๋ฆฌ๋ Œ๋”๋ง์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ด์„œ ๋”ฑํžˆ uncontrolled ํ•œ ์ƒํƒœ์— ์ด์ ์ด ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ด Controlled Input์„ ์‚ฌ์šฉํ–ˆ๋˜ ๊ฒฝํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

React Hook Form์—์„œ๋Š” Controlled Input์„ ์‚ฌ์šฉํ•  ๋•Œ์— useController / Controller ๋‘ ๊ฐ€์ง€ API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

useController์™€ Controll ์ปดํฌ๋„ŒํŠธ์˜ ๊ธฐ๋Šฅ์€ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์—, ํ•˜๋‚˜๋กœ ํ†ต์ผํ•˜๋Š”๊ฒŒ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ €๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ์ด์œ ๋กœ useController๋ฅผ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.

  • ์‚ฌ์šฉ์„ฑ ์ธก๋ฉด์—์„œ hook์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” useController๊ฐ€ ๋” ํŽธํ•œ ๋Š๋‚Œ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
  • Controller๋Š” Controller ์ปดํฌ๋„ŒํŠธ๋กœ ๊ฐ์‹ธ๊ธฐ ๋•Œ๋ฌธ์—, ๋ช…์‹œ์ ์ด์ง€ ์•Š์•„ ๋ณด์—ฌ์„œ ๊ฐ€๋…์„ฑ์ด ์ข‹์ง€ ์•Š๋‹ค๊ณ  ๋Š๊ผˆ์Šต๋‹ˆ๋‹ค.
  • controlled๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฅธ ๊ณณ์—์„œ๋„ ๋น„๊ต์  ํŽธํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋Š” .(hook์˜ return ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์— )

์ œ๊ฐ€ ๋Š๊ผˆ๋˜ ๋‹จ์ ์€, useController๋ฅผ ์‚ฌ์šฉ ์‹œ ๋งˆ๋‹ค hook์„ ์—ฌ๋Ÿฌ ์ด๋ฆ„์œผ๋กœ ๋ฐ”๊ฟ”์ค˜์•ผ ํ•˜๋Š”๊ฒŒ ๋ถˆํŽธํ–ˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜์—์„œ๋Š” ReactDatePicker๋ฅผ ์‚ฌ์šฉํ•˜๋Š” form์— ๋Œ€ํ•œ ๊ฐ™์€ ๊ธฐ๋Šฅ์„, ๊ฐ๊ฐ useController์™€ Controller๋กœ ๊ตฌํ˜„ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๋น„๊ตํ•ด๋ณด์‹œ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

useController

๊ณต์‹ ๋ฌธ์„œ: https://react-hook-form.com/docs/usecontroller

import React from "react";

type FormValues = {
  ReactDatepicker: string
}
function App() {
	const { handleSubmit, control } = useForm();
	const { field } = useController({
	name: "reactDatePicker",
	control
	});

	return (
	<form onSubmit={handleSubmit((data) => console.log(data))}>
		<ReactDatePicker
		onChange={field.onChange} // send value to hook form
		onBlur={field.onBlur} // notify when input is touched/blur
		selected={field.value}
		/>
		<button type="submit">์ œ์ถœ</button>
	</form>
	);
}

Controller

๊ณต์‹๋ฌธ์„œ: https://react-hook-form.com/docs/usecontroller/controller

import ReactDatePicker from "react-datepicker"
import { TextField } from "@material-ui/core"
import { useForm, Controller } from "react-hook-form"

type FormValues = {
  ReactDatepicker: string
}
function App() {
  const { handleSubmit, control } = useForm<FormValues>()

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <Controller
        control={control}
        name="ReactDatepicker"
        render={({ field: { onChange, onBlur, value, ref } }) => (
          <ReactDatePicker
            onChange={onChange} // send value to hook form
            onBlur={onBlur} // notify when input is touched/blur
            selected={value}
          />
        )}
      />
		<button type="submit">์ œ์ถœ</button>
    </form>
  )
}

๊ผญ ์ด ๋ถ€๋ถ„์„ ํ†ต์ผํ•˜์ง€ ์•Š๋”๋ผ๋„, register์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ control์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์˜ ์ฐจ์ด, useController๊ณผ Controller ๊ด€๋ จ ๋‚ด์šฉ์„ ๊ณต์œ ๋“œ๋ฆฌ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์„œ ๋‚ด์šฉ์„ ๊ณต์œ  ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๊ด€๋ จ discussion link ์ž…๋‹ˆ๋‹ค. https://github.com/orgs/react-hook-form/discussions/7852#discussioncomment-3692813

https://github.com/orgs/react-hook-form/discussions/6157

https://github.com/orgs/react-hook-form/discussions/7554

ํ˜น์‹œ ์ถ”๊ฐ€์ ์ธ ์ž๋ฃŒ๋‚˜ ๊ณต์œ ํ•ด์ฃผ์‹ค ์ด์•ผ๊ธฐ๊ฐ€ ์žˆ๋‹ค๋ฉด ๋” ๋งŽ์€ ๋„์›€์ด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ‹€๋ฆฐ ๋‚ด์šฉ / ๋ถ€์กฑํ•œ ๋‚ด์šฉ์— ๋Œ€ํ•œ ์ง€์ ๋„ ์–ธ์ œ๋‚˜ ํ™˜์˜์ž…๋‹ˆ๋‹ค.

@ 2025. nyoung all rights reserved