안녕하세요. 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 제공을 위해 사용
[ 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 등록 커스텀하는 방법에 대해 간단하게 알아보는 시간이었습니다.
읽어주셔서 감사합니다.
'SPA > React' 카테고리의 다른 글
[React] react-router 사용하기 (1) | 2022.08.22 |
---|---|
[React] Import에도 ESLint 적용하기 (0) | 2022.08.20 |
[React] 사용해본 yup 조건절 정리 (0) | 2022.08.11 |
[React] react-hook-form과 yup으로 동적 배열 유효성 검증하기 (1) | 2022.08.09 |
[React] 아토믹 디자인(Atomic Design) 을 이용한 컴포넌트 개발 (0) | 2022.07.13 |
댓글