이번 편에서는 Ref와 React Hooks의 기본 API 중 하나인 useRef를 알아보겠습니다.
import React from 'react'
const User = () => {
const requestToLogin = event => {
event.preventDefault()
const idReference = document.getElementById('id')
const passwordReferenece = document.getElementById('password')
const id = idReference.target.value
const password = passwordReferenece.target.value
// a AJAX logic
}
return (
<form onSubmit={requestToLogin}>
<label>
id:
<input id='id' type='text' />
</label>
<label>
password:
<input id='password' type='password' />
</label>
<button type='submit'>로그인!</button>
</form>
)
}
컴포넌트를 작성하다 보면 태그를 직접 다루어야 하는 경우도 있습니다.
해당 프로젝트 안에서 유일한 id를 지정한다면 document.getElementById
메서드로 직접 Element를 불러와서 사용할 수 있습니다.
간단한 컴포넌트라면 document.getElementById
메서드를 이용할 수도 있곘지만, 테이블처럼 반복 컴포넌트인 경우에는 아무래도 한계와 React스럽지 않다는 찜찜함도 남습니다.
다행히도 React는 해결할 수 있는 방법을 제공합니다.
import React, { createRef, useState } from 'react'
const User = () => {
const [idReference, setIdReference] = useState(() => createRef())
const [passwordReferenece, setPasswordReference] = useState(() => createRef())
const requestToLogin = event => {
event.preventDefault()
const id = idReference.current.target.value
const password = passwordReferenece.current.target.value
// a AJAX logic
}
return (
<form onSubmit={requestToLogin}>
<label>
id:
<input ref={idReference} type='text' />
</label>
<label>
password:
<input ref={passwordReference} type='password' />
</label>
<button type='submit'>로그인!</button>
</form>
)
}
useState를 이용하여 createRef 함수를 State로 생성하고 해당 State를 ref 속성에 지정하면 해당 State의 .current
를 통해서 사용할 수 있습니다.
createRef 함수로 생성한 State는 직접 Element를 지정해줄 일이 없기 때문에 useState의 2번째 return 값이 필요가 없으므로, Custom Hooks로 분리하면 깔끔하게 작성할 수 있습니다.
import React, { createRef, useState } from 'react'
const useReference = () => {
const [reference, setReference] = useState(() => createRef())
return reference
}
const User = () => {
const idReferenece = useReference()
const passwordReference = useReference()
// ...
return (
<form>
<label>
id:
<input ref={idReference} type='text' />
</label>
<label>
password:
<input ref={passwordReference} type='password' />
</label>
<button type='submit'>로그인!</button>
</form>
)
}
Custom Hooks로 작성하면 보다 깔끔하게 사용할 수 있지만, useReference는 자주 사용할 Custom Hooks인데 모든 프로젝트 마다 추가하는 것은 아무래도 번거로운 작업입니다.
React는 고맙게도 useRef 라는 이러한 기능을 지원합니다.
import React, { useRef } from 'react'
const User = () => {
const idReferenece = useRef()
const passwordReference = useRef()
// ...
return (
<form>
<label>
id:
<input ref={idReference} type='text' />
</label>
<label>
password:
<input ref={passwordReference} type='password' />
</label>
<button type='submit'>로그인!</button>
</form>
)
}
import React, { useRef } from 'react'
const User = () => {
const idReferenece = useRef()
const passwordReference = useRef()
// ...
return (
<form>
<LabelInput text='id:' type='text' ref={idReference} />
<LabelInput text='password:' type='password' ref={passwordReference} />
</form>
)
}
const LabeledInput = ({ text, type, ref }) => (
<label>
{text}
<input type={type} ref={ref} />
</label>
)
컴포넌트를 작성하다 보면 하위 컴포넌트의 Element가 필요한 경우도 있지만, ref 속성은 React에서 특별한 속성이기 때문에 위처럼 작성하면 원하는 동작을 하지 않습니다.
import React, { forwardRef, useRef } from 'react'
const User = () => {
const idReferenece = useRef()
const passwordReference = useRef()
// ...
return (
<form>
<LabelInput text='id:' type='text' ref={idReference} />
<LabelInput text='password:' type='password' ref={passwordReference} />
</form>
)
}
const LabeledInput = forwardRef(({ text, type }, ref) => (
<label>
{text}
<input type={type} ref={ref} />
</label>
))
여러 방법이 있지만 React가 지원하는 forwardRef 함수를 이용해서 해결하는 방법이 가장 깔끔합니다.
좋아요와 댓글 감사합니다.
오탈자, 질문 등은 언제든지 댓글로 달아주세요!