react-hook-form

์ž…๋ ฅ ํผ์„ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒƒ์€ ๊ฐœ๋ฐœ์„ ํ•˜๋ฉฐ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์ ‘ํ•˜๊ฒŒ ๋˜๋Š” ํ˜•์‹ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. ์•ž์„œ form ๊ฒŒ์‹œ๊ธ€์—์„œ ๋‹ค๋ค˜๋“ฏ์ด, ๊ฐ ์ž…๋ ฅ ํ•„๋“œ์˜ ์ƒํƒœ ๊ด€๋ฆฌ, ์ƒํƒœ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ, ์™„๋ฃŒ ๋กœ์ง ๋“ฑ ์ฝ”๋“œ๊ฐ€ ํ•„์—ฐ์ ์œผ๋กœ ๋งŽ์•„์ง€๊ธฐ ๋•Œ๋ฌธ์— ๋ณต์žกํ•ด์ง€๊ธฐ ์‰ฝ๋‹ค. ์ด ์ž…๋ ฅํผ์„ ๊ฐ„ํŽธํ•˜๊ฒŒ ๊ตฌํ˜„ํ• ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋ฐ”๋กœ react-hook-form ์ด๋‹ค.

react-hook-form

Performant, flexible and extensible forms with easy-to-use validation.

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

์˜ˆ์‹œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด๋„๋ก ํ•˜์ž.

import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit, watch, formState: { errors } } = useForm();
  const onSubmit = data => console.log(data);
  console.log(watch("example"));

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input defaultValue="test" {...register("example")} />
      <input {...register("exampleRequired", { required: true })} />
      {errors.exampleRequired && <span>This field is required</span>}
      <input type="submit" />
    </form>
  );
}

๋จผ์ € useForm ์ด๋ผ๋Š” ๋ชจ๋“ˆ์„ importํ•ด ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ ๋“ค์„ ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

register๋ผ๋Š” ๋ฉ”์„œ๋“œ๋Š” ๋ฌธ์ž์—ด์„ ์ธ์ž๋กœ ๋ฐ›๊ฒŒ ๋˜๋Š”๋ฐ, ํ•ด๋‹น ๋ฌธ์ž์—ด์„ ์ƒํƒœ๊ฐ’์œผ๋กœ ๋“ฑ๋กํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

handleSubmit ๋Š” ์ œ์ถœ์‹œ ์‹คํ–‰๋  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๊ฒŒ ๋œ๋‹ค. ์ดํ›„, onSubmit์˜ ์†์„ฑ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

watch๋Š” ๋‹จ์–ด ๊ทธ๋Œ€๋กœ ๋‚ด๊ฐ€ register๋กœ ์„ค์ •ํ•œ ์ƒํƒœ๊ฐ’๋“ค์˜ ํ˜„์žฌ ๊ฐ’๋“ค์„ ๋ณด์—ฌ์ค€๋‹ค.

์ด๋ ‡๊ฒŒ ๊ธฐ์กด useState๋กœ ๊ด€๋ฆฌํ•˜๋˜ ์ƒํƒœ๊ฐ’๋“ค์„ ๊ฐ„๋‹จํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ๋‹ค๋ฃฐ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค€๋‹ค. ๋˜ํ•œ ์ƒํƒœ๊ฐ’์˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์ธก๋ฉด๋„ ์ง€์›์„ ํ•˜๊ณ  ์žˆ๋‹ค.

import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit } = useForm();
  const onSubmit = data => console.log(data);
   
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("firstName", { required: true, maxLength: 20 })} />
      <input {...register("lastName", { pattern: /^[A-Za-z]+$/i })} />
      <input type="number" {...register("age", { min: 18, max: 99 })} />
      <input type="submit" />
    </form>
  );
}

inputํƒœ๊ทธ์— ์‚ฌ์šฉ๋œ register๋ฅผ ์‚ดํŽด๋ณด๋ฉด, ํ•„์ˆ˜์ž‘์„ฑ์—ฌ๋ถ€, ์ตœ๋Œ€๊ธธ์ด, ํŒจํ„ด ๋“ฑ์„ ์ง€์ •ํ•ด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๋˜ ์ˆ˜๊ณ ๋ฅผ ๋œ ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ MUI ๊ฐ™์€ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์—๋„ ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋ฉ”์„œ๋“œ๋“ค์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€? ์ด๋Ÿฌํ•œ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์€ ์ž์ฒด ์ƒํƒœ๊ด€๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„ react-hook-form๊ณผ ๊ฒฐํ•ฉ์ด ์‰ฝ์ง€์•Š๋‹ค.

react-hook-form์—์„œ๋Š” ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์„ ์œ„ํ•ด Controller๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. ์˜ˆ์‹œ์ฝ”๋“œ๋กœ ์‚ดํŽด๋ณด์ž.

import React from 'react';
import { useForm, Controller } from 'react-hook-form';
import { TextField } from '@mui/material';

type FormValues = {
  username: string;
};

export default function App() {
  const { control, handleSubmit } = useForm<FormValues>();

  const onSubmit = (data: FormValues) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="username"
        control={control}
        defaultValue=""
        render={({ field }) => (
          <TextField
            {...field}
            label="Username"
            variant="outlined"
            fullWidth
          />
        )}
      />
      <button type="submit">Submit</button>
    </form>
  );
}

์œ„ ์˜ˆ์‹œ ์ฝ”๋“œ๋Š” MUI ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ์ด๋‹ค. TextArea๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด Controller ์ปดํฌ๋„ŒํŠธ์˜ render ์†์„ฑ์— ๋„˜๊ฒจ์„œ ์‚ฌ์šฉํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ์™ธ, ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ, ์ƒํƒœ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋„ Controller๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

Last updated