티스토리 뷰
🪝 useRef()
레퍼런스를 사용하기 위한 훅
더보기
📌 리액트에서 레퍼런스란?
특정 컴포넌트에 접근할 수 있는 객체를 의미한다.
useRef()훅은 레퍼런스 객체를 반환한다.
레퍼런스 객체에는 .current라는 속성이 있는데 이것은 현재 레퍼런스(참조)하고 있는 엘리먼트를 의미한다.
const 주소값을_담는_그릇 = useRef(참조자료형-> 초기값)
📍 useRef()훅을 사용하면 파라미터로 들어온 초기값으로 초기화된 레퍼런스 객체를 반환한다.
만약, 초기값이 null이라면 .current의 값이 null인 레퍼런스 객체가 반환된다.
반환된 레퍼런스 객체는 컴포넌트의 라이프타임 전체에 걸쳐서 유지된다.
(컴포넌트가 마운트 해제 전까지는 계속 유지된다는 뜻)
➡︎ uesRef()훅은 변경 가능한 .current라는 속성을 가진 하나의 상자이다.
📍 useRef 로 DOM 노드, 엘리먼트, 그리고 React 컴포넌트 주소값을 참조할 수 있다.
React 애플리케이션을 만들때 DOM을 직접 조작하는 것은 지양해야한다.
하지만, 개발을 하다 보면 DOM을 직접 건드려야하는 상황이 발생하기도 한다.
더보기
DOM 엘리먼트의 주소값을 활용해야 하는 경우
- foucs
- text selection
- media playback
- 애니메이션 적용
- d3.js, greensock 등 DOM 기반 라이브러리 활용
이런 예외적인 상황에서 useRef로 DOM노드, 엘리먼트, 그리고 React 컴포넌트 주소값을 참조할 수 있다.
const 주소값을_담는_그릇 = useRef(참조자료형)
// 이제 주소값을_담는_그릇 변수에 어떤 주소값이든 담을 수 있습니다.
return (
<div>
<input ref={주소값을_담는_그릇} type="text" />
{/* React에서 사용 가능한 ref라는 속성에 주소값을_담는_그릇을 값으로 할당하면*/}
{/* 주소값을_담는_그릇 변수에는 input DOM 엘리먼트의 주소가 담깁니다. */}
{/* 향후 다른 컴포넌트에서 input DOM 엘리먼트를 활용할 수 있습니다. */}
</div>);
이 주소값은 컴포넌트가 re-render 되더라도 바뀌지 않는다.
이 특성을 활용하여 아래의 제한된 상황에서 useRef 를 활용할 수 있다.
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>);
}
⚠️ 주의할 점
useRef 내부의 데이터가 변경되었을 때 별도로 알리지 않는다.
.current속성을 변경하는 것은 재렌더링을 일으키지 않으므로 DOM이 연결되거나 분리되었을 경우 어떤 코드를 실행하고 싶다면 callback ref를 사용해야 한다.
제시된 상황 제외한 대부분의 경우 기본 React 문법을 벗어나useRef를 남용하는 것은 부적절하고,
React의 특징이자 장점인 선언형 프로그래밍 원칙과 배치되기 때문에, 조심해서 사용해야 한다.
✏️ 예제
1 : focus
import React, { useRef } from "react";
const Focus = () => {
const firstRef = useRef(null);
const secondRef = useRef(null);
const thirdRef = useRef(null);
const handleInput = (event) => {
console.log(event.key, event);
if (event.key === "Enter") {
if (event.target === firstRef.current) {
secondRef.current.focus();
// event.target.value = "";
} else if (event.target === secondRef.current) {
thirdRef.current.focus();
// event.target.value = "";
} else if (event.target === thirdRef.current) {
firstRef.current.focus();
// event.target.value = "";
} else {
return;
}
}
};
return (
<div>
<h1>타자연습</h1>
<h3>각 단어를 바르게 입력하고 엔터를 누르세요.</h3>
<div>
<label>hello </label>
<input ref={firstRef} onKeyUp={handleInput} />
</div>
<div>
<label>world </label>
<input ref={secondRef} onKeyUp={handleInput} />
</div>
<div>
<label>codestates </label>
<input ref={thirdRef} onKeyUp={handleInput} />
</div>
</div>
);
};
export default Focus;
2 : media playback
import { useRef } from "react";
export default function App() {
const videoRef = useRef(null);
const playVideo = () => {
videoRef.current.play();
console.log(videoRef.current);
};
const pauseVideo = () => {
videoRef.current.pause();
// videoRef.current.remove();
};
return (
<div className="App">
<div>
<button onClick={playVideo}>Play</button>
<button onClick={pauseVideo}>Pause</button>
</div>
<video ref={videoRef} width="320" height="240" controls>
<source
type="video/mp4"
src="https://player.vimeo.com/external/544643152.sd.mp4?s=7dbf132a4774254dde51f4f9baabbd92f6941282&profile_id=165"
/>
</video>
</div>
);
}
728x90
'코딩 > 코드스테이츠' 카테고리의 다른 글
[React] - 상태 관리 (Redux) (0) | 2023.02.24 |
---|---|
[React] 상태 관리 (0) | 2023.02.23 |
[React] - CDD 개발도구 (0) | 2023.02.21 |
[React] - Component Driven Development (CDD) (0) | 2023.02.20 |
[사용자 친화 웹] - UI / UX 개념과 관계성 (0) | 2023.02.16 |