React 공식문서 이해하기 (24)

Syoee·2023년 12월 4일
0

React

목록 보기
24/30
post-thumbnail

Chapter 4. Escape Hatches

#2 ref로 DOM 조작하기

학습 목차

1. 노드에 대한 ref 가져오기
2. 다른 컴포넌트의 DOM 노드에 접근하기
3. React가 ref를 첨부할 때
4. ref를 이용한 DOM 조작 모범 사례


1. 노드에 대한 ref 가져오기

  • React가 관리하는 DOM 노드에 접근하려면, 먼저 useRef 훅을 불러오자.
    import { useRef } from 'react';
  • 그런 다음 컴포넌트 내부에서 ref를 선언하자.
    const myRef = useRef(null);
  • 마지막으로, DOM 노드를 가져올 JSX 태그에 ref 속성으로 참조를 전달하라.
    <div ref={myRef}>
  • useRef 훅은 current 라고 하는 프로퍼티가 포함된 객체를 반환한다.
    처음에는 myRef.currentnull 이 될 것이다.
    React가 이 <div>에 대한 DOM 노드를 생성하면, React는 이 노드에 대한 참조를 myRef.current에 넣는다.
    그런 다음 이벤트 핸들러에서 이 DOM 노드에 액세스하고 여기에 정의된 빌트인 브라우저 API를 사용할 수 있다.
// 모든 브라우저 API를 사용할 수 있습니다. 예를 들어:
myRef.current.scrollIntoView();

2. 다른 컴포넌트의 DOM 노드에 접근하기

  • <input />과 같은 브라우저 엘리먼트를 출력하는 빌트인 컴포넌트에 ref를 넣으면, React는 해당 ref의 current 프로퍼티를 해당 DOM 노드(예: 브라우저의 실제 <input />)로 설정한다.
  • 그러나 <MyInput />과 같은 여러분이 만든 컴포넌트에 ref를 넣으려고 하면 기본적으로 null이 반환된다.
  • 문제를 알아차리는 데 도움이 되도록 React는 콘솔에 오류를 출력하기도 한다.
//Console
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
// 경고: 함수 컴포넌트에는 refs를 지정할 수 없습니다. 이 ref에 접근하려는 시도는 실패합니다. React.forwardRef()를 사용하려고 하셨나요?
  • 이는 기본적으로 React가 컴포넌트가 다른 컴포넌트의 DOM 노드에 접근하는 것을 허용하지 않기 때문이다.
  • ref는 탈출구이기 때문에 아껴서 사용해야 한다.
  • 다른 컴포넌트의 DOM 노드를 수동으로 조작하면 코드가 훨씬 더 취약해진다.
  • 대신, DOM 노드를 노출하길 원하는 컴포넌트에 해당 동작을 설정해야 한다.
    컴포넌트는 자신의 ref를 자식 중 하나에 “전달”하도록 지정할 수 있습니다.
  • 디자인 시스템에서 버튼, 입력 등과 같은 저수준 컴포넌트는 해당 ref를 DOM 노드로 전달하는 것이 일반적인 패턴이다.
    반면 양식, 목록 또는 페이지 섹션과 같은 상위 수준 컴포넌트는 일반적으로 DOM 구조에 대한 우발적 의존성을 피하기 위해 해당 DOM 노드를 노출하지 않는다.

3. React가 ref를 첨부할 때

  • React에서 모든 업데이트는 두 단계로 나뉜다.
    • 렌더링 하는 동안 React는 컴포넌트를 호출하여 화면에 무엇이 표시되어야 하는지 파악한다.
    • 커밋(commit) 하는 동안 React는 DOM에 변경 사항을 적용한다.
  • 일반적으로 렌더링 중에는 ref에 액세스하는 것을 원하지 않을 것이다.
    DOM 노드를 보유하는 ref도 마찬가지이다.
  • 첫 번째 렌더링 중에는 DOM 노드가 아직 생성되지 않았으므로 ref.currentnull이 된다.
    그리고 업데이트를 렌더링하는 동안에는 DOM 노드가 아직 업데이트되지 않았다.
    따라서 이를 읽기에는 너무 이르다.
  • React는 커밋하는 동안에 ref.current를 설정한다.
    React는 DOM이 업데이트 되기 전에는 ref.current의 값을 null로 설정하였다가, DOM이 업데이트된 직후 해당 DOM 노드로 다시 설정한다.
  • 일반적으로 이벤트 핸들러에서 ref에 접근한다.
  • ref로 무언가를 하고 싶지만 그 작업을 수행할 특정 이벤트가 없다면, Effect가 필요할 수 있다.

4. ref를 이용한 DOM 조작 모범 사례

  • Ref는 탈출구이다.
    React 외부로 나가야” 할 때만 사용해야 한다.
    일반적인 예로는 초점을 맞추거나, 스크롤 위치를 관리하거나 React가 노출하지 않는 브라우저 API를 호출하는 것이 있다.
  • 포커스나 스크롤 같은 비파괴적 동작을 고수한다면 문제가 발생하지 않을 것이다.
    그러나 DOM을 수동으로 수정하려고 하면 React가 수행하는 변경 사항과 충돌할 위험이 있다.
  • React가 관리하는 DOM 노드를 변경하지 말자.
    React가 관리하는 요소를 수정하거나, 자식을 추가하거나 제거하면, 위와 같이 일관성 없는 시각적 결과나 충돌이 발생할 수 있다.
  • 그렇다고 전혀 할 수 없다는 건 아니고, 주의가 필요하다는 의미이다.
    React가 업데이트할 이유가 없는 DOM의 일부는 안전하게 수정할 수 있다.
    예를 들어, JSX에서 일부 <div>가 항상 비어 있는 경우, React는 그 자식 목록을 건드릴 이유가 없다.
    따라서 수동으로 요소를 추가하거나 제거하더라도 안전하다.

요약

  • Ref는 일반적인 개념이긴 하지만, 대부분 DOM 엘리먼트를 보관할 때 사용한다.
  • <div ref={myRef}>를 전달해 DOM 노드를 myRef.current에 넣으라고 React에 지시한다.
  • 보통은 포커스, 스크롤, DOM 엘리먼트 측정과 같은 비파괴적인 동작에 ref를 사용한다.
  • 컴포넌트는 기본적으로 DOM 노드를 노출하지 않는다.
    forwardRef를 사용하고 두 번째 ref 인수를 특정 노드에 전달하여 DOM 노드를 노출하도록 설정할 수 있다.
  • React가 관리하는 DOM 노드를 변경하지 말자.
  • React가 관리하는 DOM 노드를 수정해야 한다면 React가 업데이트할 이유가 없는 부분을 수정하라.

React 공식 문서

https://react.dev/

React 비공식 번역 문서

https://react-ko.dev/

MDN

https://developer.mozilla.org/ko/

Wikipedia

https://ko.wikipedia.org/wiki/

profile
함께 일하고 싶어지는 동료, 프론트엔드 개발자입니다.

0개의 댓글