ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React Hook Form์˜ ์„œ๋กœ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ๋“ค์„ ๋น„๊ตํ•ด ๋ณด์ž
    TECH 2024. 2. 3. 15:46

    ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” React Hook Form์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋Š๊ผˆ๋˜ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” API๋“ค์„ ๋น„๊ตํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋ฉฐ ๋Š๋‚€ ์ ๋“ค์„ ์ •๋ฆฌํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

     

     

     

     

    1๏ธโƒฃ Controller vs. useController

    AntD, MUI์™€ ๊ฐ™์€ UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‚˜ ์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ Controller๋‚˜ useController๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ React Hook Form์˜ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
     

     

    Controller

    function Component() {
        const { control } = useForm<{type: string}>();
        
        return (
          <Controller
              control={control}
              name='type'
              render={({field : {onChange, value}}) => (
              <input
                type='input'
                value={value}
                onChange={onChange}
          	  />
             )}
          />
        )
    }

     

    Controller๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋Š๊ผˆ๋˜ ์ ์€, Controller์˜ render ์†์„ฑ์˜ return ๋ฌธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์†์„ฑ์ด ๋งŽ์•„์งˆ์ˆ˜๋ก, ๋˜๋Š” ํ•œ ์ปดํฌ๋„ŒํŠธ์— ์‚ฌ์šฉ๋˜๋Š” Controller๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ์ฝ”๋“œ ๋ผ์ธ๊ณผ ๋“ค์—ฌ์“ฐ๊ธฐ ํšŸ์ˆ˜๊ฐ€ ์ฆ๊ฐ€ํ•ด ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง„๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. 

    Controller์™€ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” useController ํ›…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     


    useController

    function Component() {
        const { control } = useForm<{type: string}>()
        const { field } = useController({ name: 'type', control })
        
        return (
            <input
              type='input'
              value={field.value}
              onChange={field.onChange}
            />
        )
    }

     

     




    2๏ธโƒฃ setValue vs. reset

    React Hook Form - useForm: reset์— ๋”ฐ๋ฅด๋ฉด reset์€ ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์„ ํ•  ๋•Œ ์šฉ์ดํ•˜๊ณ , setValue๋Š” ์†Œ๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค.
    ์ €๋Š” ๋ชจ๋“  ํผ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ๋Š” reset์„, ํŠน์ • ํ•„๋“œ๋งŒ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š” setValue๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

    import { useForm } from 'react-hook-form';  
    
    export function Component() {  
      const { setValue, reset } =  
        useForm();  
        
      // ์ƒ๋žต  
    
      useEffect(() => {  
        if (data) {  
          const {  
            title,  
            groupId,  
            address,  
            latitude,  
            longitude,  
            contents,  
            maxHumanCount,  
            date,  
            status,  
          } = data;  
    
          reset({  
              title,  
              groupId,  
              address,  
              latitude,  
              longitude,  
              contents,  
              date,  
              maxHumanCount,  
              status,  
            });  
        }  
      }, [data, reset]);  
      
      const setGroup = (groupId: string) => {  
          setValue('groupId', groupId);  
      }  
      // ์ƒ๋žต...  
    }

     

     




    3๏ธโƒฃ rules vs. schema

    Controller๋‚˜ useController๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, rules ์†์„ฑ์„ ์ง€์ •ํ•˜์—ฌ ํ•„๋“œ์˜ ๊ทœ์น™์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

     

    rules

    import { useController, useForm } from "react-hook-form";
    
    export default function App() {
      const { control } = useForm({ mode: "all" });
      const {
        field,
        fieldState: { error },
      } = useController({
        name: "text",
        control,
        rules: { required: "Text is required" },
      });
    
      return (
        <>
          <input onChange={field.onChange} value={field.value} />
          {error && <p>{error?.message}</p>}
        </>
      );
    }

     



    schema

    schema๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•ด์„œ ์‚ฌ์šฉํ•  ๋•Œ๋Š” yup, zod, joi์™€ ๊ฐ™์€ schema validation ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    import { useController, useForm } from "react-hook-form";
    import { yupResolver } from "@hookform/resolvers/yup";
    import * as yup from "yup";
    
    export default function App() {
      const schema = yup.object().shape({
        text: yup.string().required("Text is required"),
      });
    
      const { control } = useForm({ mode: "all", resolver: yupResolver(schema) });
      const {
        field,
        fieldState: { error },
      } = useController({
        name: "text",
        control,
      });
    
      return (
        <>
          <input onChange={field.onChange} value={field.value} />
          {error && <p>{error?.message}</p>}
        </>
      );
    }



     

    ๋‹ค์Œ๊ณผ ๊ฐ™์ด yup์˜ test ๋ฉ”์†Œ๋“œ๋กœ ์ปค์Šคํ…€ ์—๋Ÿฌ ํƒ€์ž…์™€ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฃผ๋กœ API ์š”์ฒญ์„ ํ†ตํ•ด ๋‹‰๋„ค์ž„ ์ค‘๋ณต ํ™•์ธ๊ณผ ๊ฐ™์€ ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์น˜๊ณ  ์‹ถ์„ ๋•Œ schema validation์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

    import { useController, useForm } from "react-hook-form";
    import { yupResolver } from "@hookform/resolvers/yup";
    import * as yup from "yup";
    
    export default function App() {
      const duplicated = ["a", "b", "c", "aa", "aaa", "bb", "bbb", "cc", "ccc"];
      const schema = yup.object().shape({
        text: yup
          .string()
          .required("Text is required")
          .test(
            "Unique",
            "Values need te be unique",
            (values) => !duplicated.includes(values)
          ),
      });
    
      const { control } = useForm({ mode: "all", resolver: yupResolver(schema) });
      const {
        field,
        fieldState: { error },
      } = useController({
        name: "text",
        control,
      });
    
      return (
        <>
          <input onChange={field.onChange} value={field.value} />
          {error && <p>{error?.message}</p>}
        </>
      );
    }



    ๋Œ“๊ธ€

Designed by Tistory.