개발을 하면서 무수히 많은 폼 요소들을 마주한다. 이 요소들 중 원하는 input요소에 focus를 하기 위해 DOM요소를 어떻게 제어해야될 지에 대해 고민하게 된다. ref라는 프로퍼티를 익히고 이를 해결해보자.
ref는 render 메서드나 return값으로 생성된 DOM 노드나 React 엘리먼트에 접근하는 방법을 제공한다. react 함수형에서는 useRef()란 훅을 사용하여 current 어트리뷰트를 가진 객체 생성 가능하며 이를 ref 프로퍼티로 넘겨줄 수 있다.
🚨 ref가 변경되도 리렌더링이 되지 않는다.
개발하면서 컴포넌트가 아닌 HTML 엘리먼트에 직접적으로 접근하여 제어할 필요가 있기 때문이다. 그렇지만 선언적으로 해결될 수 있는 문제라면 되도록 ref보다는 state로 관리하도록 지향해야 한다. ref의 바람직한 사용 사례는 아래와 같다.
import React, { useRef } from 'react';
import videoFile from './video/test.webm';
function App(){
const inputRef = useRef();
const videoRef = useRef();
const onClick = () => {
inputRef.current.disabled = true; // 1
videoRef.current.pause(); // 2
}
return (
<div>
<input type="text" ref={inputRef} />
<video ref={videoRef}>
<source src={videoFile} type="video/webm">
</video>
<button onClick={onClick}>모두 중지</button>
</div>
)
}
// Custom Hook
import { useRef, useEffect } from 'react';
const useFadeIn = () => {
const fadeInRef = useRef();
useEffect(() => {
if(fadeInRef.current){
fadeInRef.current.style.transitionProperty = 'opacity';
fadeInRef.current.style.transitionDuration = '0.3s';
fadeInRef.current.style.transitionTimingFunction = 'ease';
fadeInRef.current.style.transitionDelay = '0s';
fadeInRef.current.style.opacity = 1;
}
},[])
return { ref: fadeInRef };
}
// App.jsx
import { useFadeIn } from './useFadeIn';
const App = () => {
const fadeInTarget = useFadeIn();
return (
<div>
<p {...fadeInTarget}>fade-in test....</p>
</div>
)
}
부모 컴포넌트에서 ref를 JSX 속성으로 Child 컴포넌트로 전달하게 되고 React가 forwardRef를 통해서 함수의 매개변수의 두번째 인자로 ref를 전달하게 됩니다. 이에 부모 컴포넌트에서 해당 자식 컴포넌트로 접근하여 제어할 수 있게 됩니다.
import { forwardRef } from 'react';
const Child = forwardRef((props, ref) => {
return <button ref={ref}>{props.children}</button>
});
항상 input에서 ref를 설정하여 제어를 해봤었는데 애니메이션을 적용하는 방법을 알 수 있는 시간이여서 의미있는 공부였다. 또한 커스텀 훅으로 적용하다보니 이 부분에 대한 공부가 더 필요하다고 느껴졌다. 애니메이션 ref에 대한 부분을 지금 하고 있는 프로젝트에 적용해봐야겠다.
참고 자료
https://ko.reactjs.org/docs/refs-and-the-dom.html
https://ko.reactjs.org/docs/forwarding-refs.html
https://shylog.com/react-custom-hooks-scroll-animation-fadein/