[React] useRef

유슬기·2023년 2월 21일
1

프론트엔드

목록 보기
46/64
post-thumbnail

React에서는 DOM을 직접 조작할 수 없는데, focus나 text selection, 미디어의 재생을 관리할 때, 애니메이션을 직접적으로 실행시킬 때 등 DOM 엘리먼트의 주소값을 활용해야 하는 상황이 발생한다.

이때 사용할 수 있는 Hook이 useRef 이다.
(DOM 노드, 엘리먼트, 그리고 React 컴포넌트 주소값을 참조할 수 있다.)

아래 코드처럼 작성하면 주소값을 활용할 수 있으며, 컴포넌트가 리 렌더링 되어도 주소값은 그대로 유지된다.

const inputRef = useRef(참조자료형)
return (
    <div>
      <input ref={inputRef} type="text" />
        {/* React에서 사용 가능한 ref라는 속성에 주소값을_담는_그릇을 값으로 할당하면*/}
        {/* inputRef에는 input DOM 엘리먼트의 주소가 담긴다. */}
        {/* 향후 다른 컴포넌트에서 input DOM 엘리먼트를 활용할 수 있다. */}
    </div>);

useRef는 언제 사용하는가

useRef를 사용하는 몇 가지 예시로 살펴보자.

  1. 컴포넌트에 focus를 위치시킬 필요가 있는 경우

    예를 들어, Enter 키를 입력했을 때 다음 input으로 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) { // 첫 번째 input에서 엔터를 눌렀을 때
            secondRef.current.focus(); // 두 번째 input으로 focus
          } else if (event.target === secondRef.current) {
            thirdRef.current.focus();
          } else if (event.target === thirdRef.current) {
            firstRef.current.focus();
          } else {
            return;
          }
        }
      };
    
      return (
        <div>
          <div>
            <label>input 1 </label>
            <input ref={firstRef} onKeyUp={handleInput} />
          </div>
          <div>
            <label>input 2 </label>
            <input ref={secondRef} onKeyUp={handleInput} />
          </div>
          <div>
            <label>input 3 </label>
            <input ref={thirdRef} onKeyUp={handleInput} />
          </div>
        </div>
      );
    };
    
    export default Focus;
    • const firstRef = useRef(null): Ref 객체를 만들어준다.

    • <input ref={firstRef} onKeyUp={handleInput} />: 주소값을 활용하고자 하는 DOM에 속성으로 ref값을 설정해준다. (이벤트 핸들러 설명 생략)

    • secondRef.current.focus(): Ref 객체의 current 값은 해당 DOM을 가리킨다. 해당 DOM에 포커싱을 해주는 focus()를 호출한다.

  2. useRef로 컴포넌트 안의 변수 관리하기

    리 렌더링을 하지 않으면서 컴포넌트의 속성 정보를 조회 & 수정할 때 useRef를 활용한 변수는 아래와 같은 곳에 쓰인다.

    • setTimeout, setInterval을 통해 만들어진 id
    • scroll 위치
    • 배열에 새 항목을 추가할 때 필요한 고유값 key

    아래 코드는 배열에 새로운 항목이 추가될 때 사용할 고유한 id를 변수로 관리하는 예시이다.

    import React, { useRef } from 'react';
    import UserList from './UserList';
    
    function App() {
      const users = [
        {
          id: 1,
          username: 'curry',
          email: 'curry@example.com'
        },
        {
          id: 2,
          username: 'user1',
          email: 'user1@example.com'
        },
        {
          id: 3,
          username: 'user2',
          email: 'user2@example.com'
        }
      ];
    
      const nextId = useRef(4);
      const onCreate = () => {
    
        // 배열에 새로운 항목 추가하는 로직
    
        nextId.current += 1;
      };
      return <UserList users={users} />;
    }
    
    export default App;
    • const nextId = useRef(4): 배열의 고유값 변수로 nextId를 설정해주고, useRef() 파라타미터로 다음 id가 될 숫자 4를 넣어준다. 파라미터 값을 넣어주면 해당 값이 변수의 current 값이 된다. 그리고 nextId 변수를 수정하거나 조회하려면 .current로 접근하면 된다.

    • nextId.current += 1: .current로 변수에 접근하여 값을 업데이트 해준다.

여기까지 봤을 때 드는 의문점이 있다. useState와 다른게 뭘까?

state는 component의 props로 전달하는 등의 방법을 통해 context를 외부에서 접근이 가능하지만 useRef를 통해 생성된 ref의 조작은 정의된 컴포넌트의 내부에서만 가능하다.

이러한 특징보다 중요한 것은 useRef는 내용이 변경될 때 그것을 알려주지 않는다는 점 이다.

.current 프로퍼티의 변경은 어디에서도 관찰 가능하지 않고, 따라서 렌더링을 발생시키지 않는다.
이에 반해 stateuseState를 호출하는 순간 비동기적으로 state를 업데이트함에 따라 컴포넌트를 리렌더링한다는 차이가 있다.

profile
아무것도 모르는 코린이

0개의 댓글