[React] use-hook-form : useRef와 연결하기
:: 리렌더링을 줄이기 위해 use-hook-form을 사용하는데,
:: 비밀번호 확인(보이기/숨기기), 포커싱 등을 보면 상태를 사용하거나 난감해하는 문제를 맞이한다..내 이야기.
1. useImperativeHandle
useImperativeHandle(ref, createHandle, dependencies?)
:: 자식 컴포넌트에서 부모 컴포넌트로 특정 인스턴스 값을 전달할 때 사용
:: 주로, ref를 통해 자식 컴포넌트의 내부 메서드나 속성을 부모 컴포넌트에서 사용할 수 있도록 할 때 사용
:: 즉, 자식의 인스턴스 값을 부모에게 노출 시킴
:: 결합도가 증가함을 인지
useImperativeHandle – React
The library for web and native user interfaces
ko.react.dev
1.1 사용
const passwordConfirmRef = useRef(null)
const passwordConfirmField = register('passwordConfirm', { //
required: { value: true, message: '비밀번호 확인이 필요합니다.' },
validate: {
equals: (value, { password }) => { return password === value || '비밀번호가 일치하지 않습니다.' },
}
})
useImperativeHandle(passwordConfirmField.ref, () => passwordConfirmRef.current)
- 1) 사용할 ref와 사용하고 있던 register 추출 및 정의
useImperativeHandle(passwordConfirmField.ref, () => passwordConfirmRef.current)
1) passwordConfirmField.ref를 passwordConfirmRef.current로 바꿔서,
2) 부모가 passwordConfirmRef를 통해 해당 input 요소에 접근할 수 있도록 덮어쓰기를 함
<input
id="passwordConfirm"
type="password"
className={clsx("input", { "error-border": errors?.passwordConfirm })}
{...passwordConfirmField} // register
ref={passwordConfirmRef} // 빨대 용도의 ref
/>
위에서의 연결을 통해 passwordConfirmRef로 해당 register에 접근하여 input에 대한 정보를
<button
type='button'
onClick={() => {
if (passwordConfirmRef?.current?.type === 'password') {
passwordConfirmRef.current.type = 'text'
} else {
passwordConfirmRef.current.type = 'password'
}
console.log(passwordConfirmRef?.current)
}}>
패스워드 보기
</button>
이와 같이 조절이 가능하다
function App() {
const {
register,
formState: { errors, dirtyFields },
handleSubmit,
} = useForm()
const passwordConfirmRef = useRef(null)
const passwordConfirmField = register('passwordConfirm', { //
required: { value: true, message: '비밀번호 확인이 필요합니다.' },
validate: {
equals: (value, { password }) => { return password === value || '비밀번호가 일치하지 않습니다.' },
}
})
useImperativeHandle(passwordConfirmField.ref, () => passwordConfirmRef.current)
return (
<>
<h3 style={{ margin: 0 }}>유저 추가하기</h3>
<form className='form-wrapper' onSubmit={handleSubmit((data) => console.log(data))}>
<>
<div>
<label htmlFor='passwordConfirm' className='input-label'>패스워드 확인: </label>
<span className='input-area'>
<input
id='passwordConfirm'
type='password'
className={clsx('input', { 'error-border': errors?.passwordConfirm })}
{...passwordConfirmField}
ref={passwordConfirmRef}
/>
</span>
<div className={clsx({ 'error-text': errors?.passwordConfirm })}>
{errors?.passwordConfirm?.message}
</div>
</div>
</>
<button
type='button'
onClick={() => {
if (passwordConfirmRef?.current?.type === 'password') {
passwordConfirmRef.current.type = 'text'
} else {
passwordConfirmRef.current.type = 'password'
}
console.log(passwordConfirmRef?.current)
}}>
패스워드 보기
</button>
<button type='submit'>저장하기</button>
</form>
</>
)
}
export default App
이런 덮어쓰기가 아닌 다른 포커싱용 사용은
[React Hook Form] useRef 연결하여 사용하기
React-use-Form을 사용하다 보면, useRef를 연결하여 사용할 일(스크롤 관련이나, 포커싱 관련 이벤트를 처리할 때)이 종종 있다.예를 들어, textarea의 인풋 창을 수정할 때 value의 높이에 따라 textarea의
velog.io
를 참고하자!
참고
ASAC 수업자료