HTML에서 id를 사용해 DOM에 이름을 다는 것처럼, 리액트 프로젝트 내부에서 DOM에 이름을 다는 방법이 있다. 이게 바로 ref.
가상돔을 우회해서 실제돔 요소(컴포넌트 인스턴스)에 직접 접근할 수 있게 해준다.
왜 id를 사용하지 않고 ref를 사용할까?
리액트 컴포넌트를 사용하면 얻는 장점 중 하나가 바로 재사용성인데, JSX안에서 id를 사용하면 해당 DOM을 렌더링할때 그대로 전달되면서 컴포넌트를 여러번 사용할 때 중복된 id를 가지는 문제가 발생한다.
ref는 전역적으로 작동하지 않고 컴포넌트 내부에서만 작동한다.
DOM을 직접적으로 건드려야 할때 ref를 사용하면된다.
직접적으로 건드린다는게 뭘까?🤔
input을 focus하고자 할때
상태를 업데이트할 필요 없이 값을 저장하고 싶을 때
input태그에 onChange를 통해 입력값이 변경될때마다 상태를 변경하는 것은 불필요한 리렌더링이 발생하지 않을까? 추가로 입력값에 대한 복잡한 유효성 검사가 필요한 경우라면, 입력마다 호출되면 성능 문제가 발생할 수 있다.
// 사용예시
import { useRef } from "react"
import { useDispatch } from 'react-redux'
export default function InputLang()
const inputRef = useRef(null) // 사용자의 입력값을 저장할 용도, 객체를 반환함
const dispatch = useDispatch()
const addLanguage() => {
dispatch({
type: '새로운 언어 추가',
name: inputRef.current.value,
keyword: 'DataScience',
})
}
const onUpdateLanguage = () => {
console.log(inputRef.current.value) // 사용자가 입력한 값이 실시간으로 업데이트 되는 것을 확인할 수 있다.
}
return (
<>
<input type="text" ref={inputRef} onChange={onUpdateLanguage} /> // ref props를 useRef 객체 연결하면 value attr이 변할때 마다 inputRef.current 속성에 값을 업데이트 한다.
<button onClick={addLanguage}>add Laguage</button>
</>
)
}
컴포넌트 내부에서 DOM에 직접 접근해야할 때 사용하자!
ref를 사용하지 않고도 원하는 기능을 구현할 수 있는지 고려한 후에 활용해야한다.
컴포넌트끼리 데이터를 교류할 때는 ref를 사용하는 것은 잘못된 방법이다!