를 알아보자
Ref는 render 메서드에서 생성된 DOM 노드나 React 엘리먼트에 접근하는 방법을 제공합니다.
DOM요소에 이름을 만들어 직접 접근
리액트의 모든 컴포넌트는 reference element 를 가지고 있어 컴포넌트에 ref에 대한 변수를 설정하면 해당 컴포넌트 또는 Dom 엘리먼트를 참조할 수 있게 된다.
일반적인 HTML과 Javascript에서는 태그에 id
를 달고 접근하여
스타일링이나 어떤 변화를 가져가고는 했다.
리액트에서는 id
처럼 ref
라는 것을 붙여 직접 DOM을 선택해 접근한다.
언제씀?
state
만으로 해결이 안되고 DOM을 직접 건드려야할 때
포커스, 텍스트 선택영역, 혹은 미디어의 재생을 관리할 때.
예를 들어 다음과 같이 클릭 이벤트가 발생할 때 대상이 되는 엘리먼트 또는 하위의 엘리먼트가 아닌 경우 어떤 동작을 수행(click away
)해야 하는 경우 사용할 수 있다.
import { useEffect } from 'react';
const useClickAway = (ref: React.RefObject<HTMLElement>, handler: (event: MouseEvent) => void) => {
useEffect(() => {
const clickAwayListener = (event: MouseEvent) => {
if (!ref.current || ref.current.contains(event.target as Node)) {
return;
}
handler(event);
};
document.addEventListener('mousedown', clickAwayListener);
return () => {
document.removeEventListener('mousedown', clickAwayListener);
};
}, [ref, handler]);
};
export default useClickAway;
HTMLElement
인 ref
를 파라미터로 받아 해당 엘리먼트 외부를 클릭할 때 지정된 handler
를 수행할 수 있도록 해준다.
const refContainer = useRef(initialValue);
함수형 컴포넌트에서 ref 를 사용 할 때에는 useRef
라는 Hook 함수를 사용한다.
useRef
로부터 생성된 객체는 순수자바스크립트 객체로 current
프로퍼티 하나를 가지며
해당 ref의 current 값이 변경되어도 컴포넌트의 리렌더링에 관여하지 않는다.
또한 useRef로부터 만들어진 객체는 react 전역 저장소에 할당되기 때문에 컴포넌트의 전 생애주기동안 유지된다.
current
id에 접근한 것 처럼 dom에 직접 접근할 수 있게 된다.
예 ref.current.style.backgroundColor
import { useRef } from "react";
import "./styles.css";
export default function App() {
const ref = useRef();
const handleClick = () => {
ref.current.style.backgroundColor = "red";
};
return (
<div className="App">
<h1 ref={ref}>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={handleClick}>HELL</button>
</div>
);
}
왜 리액트에서 특정 노드에 id
를 주고 접근하는 방식을 사용하면 안될까 알아보았다.
재사용 문제
html에서 id 속성의 값은 유일해야한다.
유일하지 않으면 해당 아이디로 접근해 무언가 처리하는 것은 동작하지 않는다.
단 하나의 컴포넌트를 한 번 사용할 것이라면 모르겠지만
컴포넌트에서 아이디로 특정 노드에 접근을 처리하는 것은 해당 컴포넌트가 여러번 사용될 때 문제가 생긴다.
id
로 직접 버튼에 접근해 클릭했을 때 색깔을 변경해보았다.
아이디가 모두 같은 컴포넌트 3개가 있기 때문에 맨 처음 버튼만 색깔이 바뀔 것이고
뭘 눌러도 맨 앞에 버튼 색깔이 바뀔 것이다.
접근제어
id속성을 만들고 사용한다는 것은 현재 컴포넌트 뿐만 아니라
언제 어디에서든 id를 이용해 해당 dom에 접근할 수 있다는 것으로도 볼 수 있다.
컴포넌트에 ref
를 사용하여 특정 DOM에 접근할 수 있는 유연함을 갖추면서도
외부로부터 해당 요소로의 접근을 막을 수 있다.