본문 바로가기
SPA/React

[React] react-hook-form register 등록 방법 커스텀하기

by J4J 2022. 8. 16.
300x250
반응형

안녕하세요. J4J입니다.

 

이번 포스팅은 react-hook-form register 등록 커스텀하는 방법에 대해 적어보는 시간을 가져보려고 합니다.

 

 

 

register를 props로 넘기기

 

첫 번째 방법은 register를 props로 넘기는 방법입니다.

 

개발을 하다 보면 디자인을 입히기 위해 input, select 등의 다양한 스타일 컴포넌트를 생성하게 됩니다.

 

그러다 보면 유효성 검증을 위해 register를 등록할 때 기존에 마크업 요소들에 적용하던 방식인 다음과 같은 방식을 사용할 수 없게 됩니다.

 

const App = () => {
    return (
        <>
            <RegisterProps {...register('name')} />
        </>
    );
};

export default App;

 

 

 

이런 경우에 해결할 수 있는 방법 중 하나가 등록할 register값을 props로 넘겨주는 겁니다.

 

다음과 같은 절차를 통해 코드를 작성할 수 있습니다.

 

 

 

[ 1. 사용할 컴포넌트에 register를 props로 전달 ]

 

import * as React from 'react';
import { useForm } from 'react-hook-form';
import * as yup from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';
import RegisterProps from './registerProps';

interface Form {
    name: string;
}

const App = () => {
    const schema = yup.object().shape({
        name: yup.string().required('이름을 입력해주세요.'),
    });

    const {
        handleSubmit,
        formState: { errors },
        register,
    } = useForm<Form>({
        resolver: yupResolver(schema),
        defaultValues: {
            name: '',
        },
    });

    const clickCheck = () => {
        alert('Success');
    };
   
    return (
        <>
            <button onClick={handleSubmit(clickCheck)}>검증</button>
            <RegisterProps register={register('name')} />
            {errors.name && errors.name.message}
        </>
    );
};

export default App;

 

 

 

[ 2. 검증 컴포넌트는 register를 전달받아 마크업에 등록 ]

 

import * as React from 'react';
import { UseFormRegisterReturn } from 'react-hook-form';
import styled from 'styled-components';

interface Props {
    register?: UseFormRegisterReturn;
}

const RegisterProps = React.forwardRef((props: Props, ref) => {
    return (
        <Wrapper>
            <input type="text" {...props.register} />
        </Wrapper>
    );
});

export default RegisterProps;

const Wrapper = styled.div``;

 

 

반응형

 

 

Controller 사용하기

 

개발하시는 많은 분들 중에서는 위의 방법과 같은 props로 register를 넘길 수 없는 상황들을 겪으실 수 있습니다.

 

대표적인 케이스가 material-ui 등과 같은 ui component를 가져와 사용하시는 분들입니다.

 

이런 상황에서는 react-hook-form에서 제공해주는 Controller를 이용하면 쉽게 해결할 수 있습니다.

 

사용 방법은 다음과 같습니다.

 

 

 

[ 1. 컴포넌트를 가져와 사용하는 파일 ]

 

import * as React from 'react';
import { Controller, useForm } from 'react-hook-form';
import * as yup from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';
import UseController from './useController';

interface Form {
    name: string;
}

const App = () => {
    const schema = yup.object().shape({
        name: yup.string().required('이름을 입력해주세요.'),
    });

    const {
        handleSubmit,
        formState: { errors },
        control,
    } = useForm<Form>({
        resolver: yupResolver(schema),
        defaultValues: {
            name: '',
        },
    });

    const clickCheck = () => {
        alert('Success');
    };
    
    return (
        <>
            <button onClick={handleSubmit(clickCheck)}>검증</button>
            <Controller
                control={control}
                name="name"
                render={({ field: { onChange, onBlur, value, ref } }) => (
                    <UseController ref={ref} value={value} onChange={onChange} />
                )}
            />
            {errors.name && errors.name.message}
        </>
    );
};

export default App;

 

 

 

Controller 속성 값에 대한 설명은 다음과 같습니다.

 

  • control → useForm에서 제공하는 control을 등록
  • name → 유효성 검증하려는 변수명 입력
  • render → 검증이 필요한 컴포넌트 등록

 

 

 

render에서 제공되는 field 값에 대한 설명은 다음과 같습니다.

 

  • onChange → 컴포넌트에서 발생된 onChange 이벤트를 hook form에 전달
  • onBlur → 컴포넌트에서 발생된 onBlur 이벤트를 hook form에 전달
  • value → 현재 hook form에 저장되어 있는 Controller에 등록된 name의 value값
  • ref → error가 발생되었을 때 focusing 제공을 위해 사용

 

 

728x90

 

 

[ 2. 유효성 등록될 컴포넌트 파일 ]

 

import * as React from 'react';
import styled from 'styled-components';

interface Props {
    value?: number | string;
    onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
}

const UseController = React.forwardRef((props: Props, ref: React.LegacyRef<HTMLInputElement>) => {
    return (
        <Wrapper>
            <input type="text" onChange={props.onChange} ref={ref} />
        </Wrapper>
    );
});

export default UseController;

const Wrapper = styled.div``;

 

 

 

추가로 위의 예시에서 material-ui를 얘기했기 때문에 material-ui에서도 어떻게 사용되는지에 대해서 간단히 보여드리겠습니다.

 

material-ui에서 제공해주는 TextField를 예시로 한다면 다음과 같이 사용할 수 있습니다.

 

import * as React from 'react';
import { Controller, useForm } from 'react-hook-form';
import * as yup from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';
import { TextField } from '@material-ui/core';

interface Form {
    name: string;
}

const App = () => {
    const schema = yup.object().shape({
        name: yup.string().required('이름을 입력해주세요.'),
    });

    const {
        handleSubmit,
        formState: { errors },
        control,
    } = useForm<Form>({
        resolver: yupResolver(schema),
        defaultValues: {
            name: '',
        },
    });

    const clickCheck = () => {
        alert('Success');
    };

    return (
        <>
            <button onClick={handleSubmit(clickCheck)}>검증</button>
            <Controller
                control={control}
                name="name"
                render={({ field: { onChange, onBlur, value, ref } }) => (
                    <TextField inputRef={ref} label="Standard" variant="standard" value={value} onChange={onChange} />
                )}
            />
            {errors.name && errors.name.message}
        </>
    );
};

export default App;

 

 

 

 

 

 

 

이상으로 react-hook-form register 등록 커스텀하는 방법에 대해 간단하게 알아보는 시간이었습니다.

 

읽어주셔서 감사합니다.

 

 

 

728x90
반응형

댓글