Closed hakyoung12 closed 3 weeks ago
<FormField label={<BasicLabel label={'이름'} isRequired={true} />}>
<FormInput
id="name"
name="name"
label="name"
placeholder="이름을 입력해주세요"
limit={50}
editable={true}
required={true}
/>
</FormField>
import React, { useEffect } from 'react';
import classNames from 'classnames';
import InputField, { InputProps } from '../InputField/InputField';
import { FieldValues, Path, RegisterOptions, useFormContext } from 'react-hook-form';
import './FormInput.scss';
import { addHyphenPhoneNum } from '../../../lib/utils';
export type FormInputProps<TFormValues extends FieldValues> = {
name: Path<TFormValues>;
rules?: RegisterOptions;
label: string;
value?: string;
editable: boolean;
required: boolean;
limit?: number;
} & Omit<InputProps, 'name'>;
export const FormInput = <TFormValues extends Record<string, unknown>>({
name,
rules,
className,
value,
editable = true,
required = false,
limit,
...props
}: FormInputProps<TFormValues>): JSX.Element => {
const { register, formState, watch, setValue } = useFormContext();
const { errors } = formState;
const hasError = !!errors?.[name];
const watchedValue = watch(name);
useEffect(() => {
if (name === 'phone') {
setValue(name, addHyphenPhoneNum(watchedValue));
}
}, [watchedValue, name, setValue]);
const fieldType = name === 'password' || name === 'passwordConfirm' ? 'password' : props.type;
return (
<div className={classNames('form-input', className)} aria-live="polite">
<InputField
{...props}
className={classNames()}
value={value}
hasError={hasError}
{...(register && register(name, { ...rules, required, maxLength: limit }))}
readOnly={!editable}
type={fieldType}
/>
<p className="error-message" data-testid={`${name}-error`}>
{hasError ? (watchedValue?.length ? errors?.[name]?.message : '필수 정보입니다.') : null}
</p>
</div>
);
};
✏️ 작업 내용
-로그인 페이지 레이아웃 작성 -회원가입 페이지 레이아웃 작성 -클라이언트에서 할 수 있는 유효성 검사 추가
📷 스크린샷
로그인 페이지
회원가입 페이지
폼 내용 채우지 않을 시 제출 버튼 비활성화
제출버튼 활성화
유효성 검사 오류 화면
✍️ 사용법
🎸 기타