[React] useRef란?

강 수정·2024년 2월 29일
0
post-thumbnail

💠 useRef

useRef는 렌더링에 필요하지 않은 값을 참조할 수 있는 React 훅이다. - 📎 공식문서


1️⃣ 저장공간으로서의 기능

우리는 값을 저장하는 개념을 3가지로 나누어서 생각해볼 수 있다.

  1. 변수
    -UI상 표현되지 않는 값이다.
    -state 변화를 통해 UI를 렌더링 하는 순간 변수가 초기화된다.

  2. state
    -UI상 표현되는 값이다.
    -화면을 새로고침하지 않는 한, 값이 유지된다.
    -화면에 보여지는 값이기 때문에 state가 변화할 때마다 매번 컴포넌트가 마운트되고, 리렌더링이 일어난다. 이것은 성능상 문제로 이어질 수 있다.

  3. useRef
    -UI상 표현되지 않는 값이다.
    -라이프 사이클 주기동안 값이 유지된다.

    Changing a ref does not trigger a re-render. This means refs are perfect for storing information that doesn’t affect the visual output of your component. - 공식문서 중

    공식문서는 useRef를 사용하면 ref를 변경해도 리렌더링을 촉발하지 않아서 컴포넌트의 시각적 출력에 영향을 미치지 않는 정보를 저장하는 데 적합하다고 설명한다.

    따라서 useRef의 특징을 다음과 같이 정리할 수 있다.

  • (렌더링할 때마다 재설정되는 일반 변수와 달리) 리렌더링 사이에 정보를 저장할 수 있다.
  • (리렌더링을 촉발하는 state 변수와 달리) 변경해도 리렌더링을 촉발하지 않는다.
  • (정보가 공유되는 외부 변수와 달리) 각각의 컴포넌트에 로컬로 저장된다.


📌 예시1. 불필요한 api 호출 막기

사용자가 똑같은 검색어를 입력하면 불필요한 api 호출이 발생한다. 이럴 때 useRef를 이용해서 지난 검색어를 저장한 후, 버튼을 눌렀을 때 useRef의 current값이 현재 value와 동일하다면 api 호출하지 않도록 만들 수 있다.

import { ChangeEventHandler, useRef, useState } from 'react';

export default function Home() {
	const [keyword, setKeyword] = useState('');
	const prevKeywordRef = useRef('');
	const handleChange: ChangeEventHandler<HTMLInputElement> = (e) =>
		setKeyword(e.target.value);
	const fetchSearch = () => console.log('api 호출 시작! ');
	const handleSearch = () => {
		if (prevKeywordRef.current !== keyword) {
			fetchSearch();
			prevKeywordRef.current = keyword;
		}
	};
	return (
		<form>
			<input
				type="text"
				value={keyword}
				onChange={handleChange}
				placeholder="검색어를 입력하세요"
			/>
			<button
				type="button"
				onClick={handleSearch}
			>
				검색
			</button>
		</form>
	);
}



2️⃣ DOM 요소 선택 기능

📌 예시2. 못생긴 파일선택 개선

<input type="file" />은 다음과 같이 나타난다.


남들은 이렇게 UI를 개선하던데, 어떻게 하는 것일까? 하던 과거의 무지했던 나..
답은 useRef에 있었다!

'use client';

import React, { ChangeEventHandler, useRef, useState } from 'react';

export default function Page() {
	const imageRef = useRef<HTMLInputElement>(null);
	const [profileImg, setProfileImg] = useState<File>();
	const onClickButton = () => imageRef.current?.click();
	const handleChangeImage: ChangeEventHandler<HTMLInputElement> = (e) => {
		const files = e.target?.files;
		if (files && files[0]) {
			setProfileImg(files[0]);
		}
	};
	return (
		<div>
			<div>
				<label
					htmlFor="image"
					className="font-bold"
					hidden
				>
					프로필 이미지
				</label>
				<input
					id="image"
					name="image"
					type="file"
					accept="image/*"
					hidden
					ref={imageRef}
					onChange={handleChangeImage}
				/>
				<button
					type="button"
					onClick={onClickButton}
				>
					{/* 원하는 버튼 이미지 (svg파일 등) */}
				</button>
			</div>
		</div>
	);
}
  1. <input type="file" />hidden으로 만들고, ref을 만들어 DOM조작이 가능하게 한다.
  2. button의 onClick 이벤트 헨들러에 () => imageRef.current?.click();을 추가하여 ref의 current을 이용하여 input DOM요소를 대신 click하도록 만든다.

📌 예시3. 상단 이동 스크롤 버튼 만들기

컨텐츠가 많은 사이트를 보면 어디에서나 볼 수 있는 버튼이 있다.


이렇게 생긴 디자인의 버튼을 한 번쯤 본 적이 있을 것이다.
useRef을 이용하면 뷰포트 상단으로 이동하는 기능을 쉽게 만들 수 있었다 !

import { useRef } from 'react';

export default function ScroppToTop() {
	const topRef = useRef<HTMLDivElement | null>(null);
	const handleToTop = () => {
		if (topRef.current) {
			topRef.current.scrollIntoView({ behavior: 'smooth' });
		}
	};
	return (
		<div>
			<div ref={topRef} />
			<button onClick={handleToTop}> 최상단 이동</button>
		</div>
	);
}

화면의 최상단 부분에 해당하는 컨텐츠에 ref를 달고, button의 onClick 이벤트에 scrollIntoView를 이용하여 화면 상단으로 이동시킬 수 있다.

공식문서에서 scrollIntoView를 이용하여 각 이미지에 해당하는 버튼을 누르면 해당 이미지로 포커스되어 이동하는 예제도 있으니 참고하면 좋겠다. - 📎공식문서

profile
주니어 개발자 깡수 개발일지

0개의 댓글