[React] Ref

DongHyeon Jung·2022년 9월 21일
0

React

목록 보기
6/15
post-thumbnail

Ref

ref는 특정 컴포넌트에 접근하는데 사용된다
ref에 관한 수많은 블로그 글을 보았고, 강의도 들었지만 정확한 개념이 잘 이해되지 않는다…(좀 추상적?)
목표는 ref가 정확이 무엇인지, prop과 state와의 명확한 차이점이 무엇인지, state와의 차이점은 무엇인지, 왜 남용하면 안되는지를 파악하는 것이다.

목차

  • Why we use Ref?
  • What is Ref?
  • When we use Ref?
  • How to use Ref?
  • State vs Ref
  • props vs Ref
  • 남용하면 안되는 이유?
  • 참고한 레퍼런스

Why we use Ref?

일반적으로 부모 자식 컴포넌트 간에 props로 상호작용한다
자식을 수정하려면 새로운 props를 전달하여 다시 렌더링해야한다 →
따라서 React 만으로 DOM을 조작하기 어려울 때 사용한다
그러나, 일반적인 데이터 플로우에서 벗어나
직접적으로 자식을 수정해야 하는 경우도 가끔씩 있다.
예를 들면 vanilla js에서 DOM을 조작하려면 선택자를 이용한다

const myElement = document.querySelector('#my-id');
myElement.style.color = 'red';

하지만 React에서 DOM을 직접 수정하려면 ref를 사용한다.

  1. 저장공간
    state변화 → 렌더링 → 컴포넌트 내부 변수들 초기화
    ref의 변화 → no 렌더링 → 변수들 값 유지, state값이 변화해도 ref의 값은 유지됨

  2. DOM 요소에 접근
    input요소 등에 접근이 용이
    document.querySelector와 비슷한 역할을 한다

When we use Ref?

  • 포커스, 텍스트 선택영역, 혹은 미디어의 재생을 관리할 때.
  • 애니메이션을 직접적으로 실행시킬 때.
  • 서드 파티 DOM 라이브러리를 React와 같이 사용할 때.

즉 state만으로 해결할 수 없는 기능

  • 특정 input에 포커스 주기
  • 스크롤 박스 조작하기
  • canbus 요소에 그림그리기 등…

DOM에 접근해야 할 때 ref를 사용한다.

왜냐하면 useState로 생성한 변수가 아닌 이상, 다른 변수들이 변경되더라도 컴포넌트가 리렌더링 되지 않기 때문이다.

state로만 해결할 수 없고, “DOM을 반드시 직접 건드려야 할 때!!!” 사용된다

What is Ref ?

ref는 render 메서드에서 생성된 DOM 노드나 React 엘리먼트에 접근하는 방법을 제공합니다. - 공식문서
reference를 의미한다 - 참조
useRef 라는 Hook API를 이용한다

import { useRef } from 'react'

const refContainer = useRef(initialValue);

useRef를 사용해서 렌더링에 관여하지 않는 변수를 만든다
(렌더링을 발생시키지 않고 렌더링을 해도 남아있는)
그리고 이것은 전역적으로 작동하지 않고 내부에서만 작동한다.
useRef로 선언한 객체는 컴포넌트와 생애주기를 함께한다??? → (생애주기는 다음에..)

useRef는 무엇인가?

useRef는엘리먼트 ref용 값을 선언할 때 사용하는 Hook
but 함수를 재호출하더라도 생애주기(lifecycle) 동안은 current를 유지한다
useRef로 생성된 객체 refContainer 는 current값이 변화해도 렌더링에 관여하지 않는다.
그 이유는…? useRef()가 순수 자바스크립트 객체를 생성하기 때문!!!

inputRef.current.value = 'some value';

여기서 state를 업데이트 하지 않는다 → 렌더링 하지 않는다.
ref 안의 current에 저장된다
컴포넌트가 렌더링되어도 언마운트되기 전에는 값이 유지된다.

How to use Ref?

function App() {
  const [name, setName] = useState('');
  const prevName = useRef('');
  // prevName is just object current property -> prevName.current

  useEffect(() => {
    prevName.current = name;
  }, [name]);
  // using ref => we don't actually need so
  // 필요하지 않다면 렌더링을 일으키지 않음...
  // 리렌더링하지 않고 DOM에 접근, 값 유지

  return (
    <>
      <input value={name} onChange={event => setName(event.target.value)} />
      <div>
        My name is {name} and it used to be {prevName.current}
      </div>
    </>
  );
}
 const prevName = useRef('');

useRef를 통해 생성된 객체 prevName → 컴퍼넌트가 변경되어 렌더링할때마다 객체의 current 프로퍼티가 컴포넌트의 DOM 객체로 설정됨.

React는 노드가 변경될 때마다 변경된 DOM 노드에 그것의 .current 프로퍼티를 설정함

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

State vs Ref

Ref는 state와는 다르게 값이 바뀌어도 다시 렌더링을 일으키지 않는다

const renderCount = useRef(0);

useEffect(() => {
    renderCount.current = renderCount.current + 1;
  });

return (
    <>
      <input value={name} onChange={event => setName(event.target.value)} />
      <div>My name is {name}</div>
      <div>I rendered {renderCount.current} times</div>
    </>

0개의 댓글