[TIL #13] React (Hooks) - useRef 란?

JMinkyoung·2021년 7월 22일
0

TIL

목록 보기
13/42
post-thumbnail

앞에서부터 계속 다루고 있는 Hook API.. 강의를 들으면서, 혼자 토이 프로젝트를 진행하면서 그때그때 마주치게 되는 개념들을 하나씩 쓰다보니 Hooks 관련 포스트만 5개로 나눠져버렸다 😂

...아무튼 오늘은 간단하지만 가끔 헷갈리는! useRef에 대해서 자세히 다뤄보자 🏃‍♂️

useRef 란?

useRef란 어떠한 특정 DOM을 선택할 수 있게 해준다. 코딩을 하다보면 DOM을 직접 선택해서 포커스를 주거나 특정 엘리먼트의 크기나 색상을 변경하는 경우가 있는데 그때 사용하는 것이다.

DOM 이란?
HTML과 JavaScript를 이어주는 공간으로, 작성한 HTML을 JavaScript가 이해할 수 있도록 Object로 변환하는 것이다. 출처
(DOM에 대해서는 따로 다룰 예정이다!)

React 공식문서에 적혀있는 useRef의 기본 구조와 설명은 다음과 같다.

const refContainer = useRef(initialValue);

"useRef.current 프로퍼티로 전달된 인자 (initialValue)로 초기화된 변경 가능한 ref 객체를 반환한다. 반환된 객체는 컴포넌트의 전 생애 주기를 통해 유지될 것이다 "

설명만 봐서는 뭔소린지 도통 알수가 없다.. 예제를 통해서 이해해보자 🤯


useRef(Focus) 예제

import React, { useState, useRef } from "react";
import "./styles.css";

const App = () => {
  const [name, setName] = useState("");
  const [nickname, setNickname] = useState("");

  const onChangename = (e) => {
    setName(e.target.value);
  };
  const onChangenickname = (e) => {
    setNickname(e.target.value);
  };
  // useRef 객체 생성
  const ref = useRef();

  const onClickReset = () => {
    setName("");
    setNickname("");
    // 버튼 클릭시 지정한 위치에 focus 되도록
    ref.current.focus();
  };

  return (
    <div>
      {/* 원하는 위치에 ref 값 설정한다 */}
      <input value={name} onChange={onChangename} ref={ref} />

      <input value={nickname} onChange={onChangenickname} />
      <button onClick={onClickReset}>RESET</button>
      <div>
        <h3>결과</h3>
        <h4>
          {name} 의 별명은 {nickname} 입니다.
        </h4>
      </div>
    </div>
  );
};

export default App;

이름(name)과 별명(nickname)을 입력하면 화면에 띄우고, RESET 버튼을 누르면 이름과 별명을 초기화하고 원하는 위치 (위 코드에선 name 입력받는 input)로 focus 되도록 하는 예제이다.
핵심 코드만 한번 살펴보자!

1. useRef 객체를 생성한다

 // useRef 객체 생성
  const ref = useRef();

2. 선택하고 싶은 DOM에 ref 값으로 객체 넣기

 {/* 원하는 위치(DOM)에 ref 값 설정한다 */}
 <input value={name} onChange={onChangename} ref={ref} />

3. 객체를 통해 수행하고 싶은 작업 설정

  const onClickReset = () => {
    setName("");
    setNickname("");
    // 버튼 클릭시 지정한 위치에 focus 되도록
    ref.current.focus();
  };

RESET 버튼을 클릭하면 Focus가 위에서 설정한 name input으로 이동하는 것을 확인 할 수 있다.

 <input value={nickname} onChange={onChangenickname} ref={ref} />

만약 nickname input에 ref를 설정하게 되면 결과는 다음과 같이 변하게 되는 것을 확인 할 수 있다.


useRef(변수 관리) 예제

useRef 특정 DOM을 선택하는 용도 이외에도 Component 안에서 조회 및 수정이 가능한 변수를 관리하는 용도로도 사용된다.
하지만 useRef 이용해서 변수를 업데이트 하게 되면 해당 Component가 리렌더링 되지 않기 때문에 리렌더링을 원한다면 callback ref를 사용해야 한다.
but ! 굳이 리렌더링이 필요없는 변수를 다룰때는 useRef를 사용하는 것이 효율적이다!

useRef를 통해 관리되는 변수가 주로 쓰이는 곳

  • setTimeout, setInterval을 통해 만들어진 id
  • scroll의 위치
  • 배열에 새 항목이 추가 될 때 필요한 고유 key 값
  • 외부 라이브러리를 사용하여 생성된 인스턴스
import React, {useRef} from 'react';
import UserList from './UserList';

const App = () => {
  const users = [
    {
      id:1,
      name: '김채원'
    },
    {
      id:2,
      name: '푸푸'
    },
    {
      id:3,
      name: '쌈무'
    }
  ];

  const nextId = useRef(4);
  const onCreate = () => {
    // 배열에 항목 추가하는 부분 생략
    nextId.current += 1; 
  };
  return <UserList users={users}/>;
}

export default App;

현재 users라는 배열에 3명의 user가 존재하기 때문에 다음에 추가되면 해당 user의 id = 4 가 되므로 const nextId = useRef(4); 를 통해 .current의 기본값을 설정해준다.
그 후 배열을 추가하는 부분에 새로 추가되는 배열의 id 값을 nextId.current += 1;을 통해 1 증가시키고 해당 값을 넣어주면 된다.

여기서 드는 한가지 의문점..

let nextId = 4;

이렇게 변수를 선언하고 값을 증가시켜주면 되는거.. 아닌가??
할수도 있지만 함수형 컴포넌트 안에서 변수를 위처럼 선언하게 되면 리렌더링 될 때마다 값이 4로 초기화 되기 때문에 배열에 대참사가 일어날 수 있다 😵


참고 자료1
참고 자료2
참고 자료3

profile
Frontend Developer

1개의 댓글

comment-user-thumbnail
2022년 7월 18일

이해가 잘되네요 감사합니다~

답글 달기