React.js/React-hook-form

react-hook-form에서 useController 커스텀 훅 사용

Dev갱이 2024. 6. 25. 19:20
728x90
input 타입의 time 필드가 여러개가 존재 할때 재사용할 수 있는 컴포넌트를 만들때 useController 커스텀훅을 사용하면 좋을것 같았다.

 

재사용 컴퍼넌트를 만들때 useController에서 사용하고자 하는 props를 정의 해주어야 한다.
control, name, validationOptions

 

// FieldTime.tsx

import React from 'react';
import { Control, Path, RegisterOptions, useController } from 'react-hook-form';
import Field from '../Field';

interface Props<T extends Record<string, any>> {
	control: Control<T>;
	name: Path<T>;
	validationOptions?: Omit<
		RegisterOptions<T, Path<T>>,
		'valueAsNumber' | 'valueAsDate' | 'setValueAs' | 'disabled'
	>;
}

const FieldTime = <T extends Record<string, any>>(props: Props<T>) => {
	const { control, name, validationOptions } = props;

	const {
		field,
		fieldState: { invalid, isTouched, isDirty, error },
		formState: { touchedFields, dirtyFields },
	} = useController({
		name,
		control,
		rules: { ...validationOptions },
	});

	return (
		<Field
			fieldClass={'inline_input'}
			labelText={'시작시간'}
			onChange={field.onChange}
			name={field.name}
			value={field.value}
			className="w-full  md:text-base text-sm"
			type="time"
			error={error && error}
		/>
	);
};

export default FieldTime;
이렇게 재사용 컴퍼넌트를 만들고 난 후에 부모 컴퍼넌트에서 useForm을 이용하여 register와 control을 둘다 사용할 수 있다.

 

// 부모 컴포넌트
const {
		register,
		formState: { errors, isValid },
		handleSubmit,
		reset,
		getValues,
		watch,
		control,
	} = useForm<{
		eventName: string;
		eventDescription: string;
		eventStartTime: string;
	}>({
		mode: 'onChange',
	});
    
    ... 중략
    
    	<div className={styles.field_container}>
            <Field
                fieldClass={'inline_input'}
                labelText={'이벤트 이름'}
                {...register('eventName', {
                    required: '이벤트 이름은 필수입니다!',
                    minLength: {
                        value: 2,
                        message: '최소 이름은 2자 이상입니다.',
                    },
                })}
                placeholder="이벤트 이름을 입력 해주세요!"
                error={errors.eventName}
            ></Field>
            <FieldWithTextarea
                fieldClass={'inline_textarea'}
                labelText={'이벤트 설명'}
                {...register('eventDescription', {
                    maxLength: {
                        value: 1000,
                        message: '최대 1000자까지 가능합니다',
                    },
                })}
                placeholder="상세 정보를 추가하세요"
                error={errors.eventDescription}
            ></FieldWithTextarea>

            {/* <Field
                fieldClass={'inline_input'}
                labelText={'시작시간'}
                {...register('eventStartTime', {
                    required: '시작시간을 필수입니다!',
                })}
                className="w-full  md:text-base text-sm"
                type="time"
                error={errors.eventStartTime}
            /> */}
            <FieldTime
                control={control}
                name="eventStartTime"
                labelText="시작시간"
                validationOptions={{
                    required: '시작시간을 필수입니다!',
                }}
            ></FieldTime>
        </div>
    
    ... 중략

 

register를 사용하거나 control로 재사용 컴포넌트를 사용해서 사용하거나 할 수 있어서 react-hook-form이 굉장히 강력한것 같다.

 

 

Reference

https://react-hook-form.com/docs/usecontroller

 

useController

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

react-hook-form.com

https://velog.io/@boyeon_jeong/React-Hook-Form-Controller-useController-y6v2mfc9

 

[React Hook Form] mui와 같이 사용하기 | Controller, useController

제어 컴포넌트(https://legacy.reactjs.org/docs/forms.htmlReact에서 제어 컴포넌트는 폼 요소뿐만 아니라 일반적인 컴포넌트에서도 사용될 수 있습니다. 그러나 폼 요소를 제어 컴포넌트로 사용하는 것이

velog.io

 

728x90