리액트 공식문서에서는 "본질적으로 useRef는 .current 프로퍼티에 변경 가능한 값을 담고 있는 “상자”"와 같다고 설명한다. 이렇게 설정된 상자는 "노드가 변경될 때마다 변경된 DOM 노드에 그것의 .current 프로퍼티"를 통하여 조작이 가능해진다는 것을 의미한다.
const App = () => {
const inputRef = useRef();
useEffect(()=> {
// document.getElementById('input').focus()
inputRef.current.focus()
},[])
return (
<>
<input id="input" ref={inputRef}/>
</>
)
}
input 태그에 ref 속성을 통하여 선언한 inputRef(useRef)를 연결해준다. 이렇게 연결된 태그의 이름(상자)는 inputRef.current를 통하여 접근이 가능한데, useEffect()를 통해서 화면이 새로고침되었을 때, 바로 해당위치를 focus() 하도록 설정하면 되는 것이다. 물론 이러한 효과는 바닐라 JS에서 getElementById('input').focus()와 같이 id 값을 통하여 접근했던 방식과 동일하다. 그러나 리액트 환경에서 굳이 useRef를 생성한 것은 최적화의 문제이다. 리액트가 관장하고 있는 환경에서 해당 작업이 진행되기 때문인 것이다.
위의 이미지에서 가변적인 div 태그의 색상 변화는 useRef를 통해서 가변적으로 생성한 것이다. 아래의 코드를 살펴보자.
const App = () => {
const inputRef = useRef();
const divRef = useRef();
useEffect(()=> {
inputRef.current.focus()
setInterval(()=>{ // 반복실행
divRef.current.style.backgroundColor = "pink"
setTimeout(()=> { // 시간차 실행
divRef.current.style.backgroundColor = "orange"
}, 500)
}, 1000)
},[])
return (
<>
<input id="input" ref={inputRef}/>
<div ref={divRef} style={{height:"100px", width:"100px", backgroundColor:"orange"}}/>
</>
)
}
useRef이 동작하는 로직이 useEffect 안에 담겨져 있으며, 이 안에 setInterval을 통하여 반복적으로 실행될 로직과 그 안에서 setTimeout을 통하여 시간의 격차를 두고 실행될 로직을 작성하였다. 최초로 화면이 마운트 된 이후, setInterval에 담긴 로직을 통해서 div태그는 핑크로 색이 변경될 것이다. 그리고 0.5초가 흐른 시점에서 setTimeout이 동작하며 다시 색이 오랜지로 변경될 것이고, 0.5초 뒤(setInterval 선언 이후 1초)가 되면 다시 색이 핑크로 변경되며, 즉 0.5초마다 색이 변경되는 효과를 줄 수 있는 예제를 추가해보았다.