[React] 🐟useRef 사용법

TATA·2023년 2월 22일
0

React

목록 보기
11/32

▷ useRef

DOM reference를 잘 활용할 수 있는 useRef

아래와 같이 DOM 엘리먼트의 주소값을 활용해야 하는 경우에 사용한다.

- focus
- text selection
- media playback
- 애니메이션 적용
- d3.js, greensock 등 DOM 기반 라이브러리 활용

React는 이런 예외적인 상황에서 useRef로
DOM 노드, 엘리먼트, 그리고 React 컴포넌트 주소값을 참조할 수 있다.


🐟 기본 구조

컴포넌트가 re-render 되더라도 주소값은 바뀌지 않는다.

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

🐟 간단한 예시

ref는 자신이 전달받은 DOM 엘리먼트current 프로퍼티의 값으로서 받는다.

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
      // 버튼 클릭 후에도 input창이 파란색으로 포커스 되어있다.
    </>);
}

❗️참고) 제시된 상황을 제외한 대부분의 경우에는 기본 React문법을 벗어난다. useRef를 남용하는 것은 부적절하기에 조심해서 사용해야 함.


🐟 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) {
        secondRef.current.focus();
        event.target.value = "";
      } else if (event.target === secondRef.current) {
        thirdRef.current.focus();
        event.target.value = "";
      } else if (event.target === thirdRef.current) {
        firstRef.current.focus();
        event.target.value = "";
      } else {
        return;
      }
    }
  };

  return (
    <div>
      <h1>타자연습</h1>
      <h3>각 단어를 바르게 입력하고 엔터를 누르세요.</h3>
      <div>
        <label>hello </label>
        <input ref={firstRef} onKeyUp={handleInput} />
      </div>
      <div>
        <label>TATA </label>
        <input ref={secondRef} onKeyUp={handleInput} />
      </div>
      <div>
        <label>Velog </label>
        <input ref={thirdRef} onKeyUp={handleInput} />
      </div>
    </div>
  );
};

export default Focus;


🐟 media playback 예제

import { useRef } from "react";

export default function App() {
  const videoRef = useRef(null);

  const playVideo = () => {
    videoRef.current.play();
    console.log(videoRef.current);
  };

  const pauseVideo = () => {
    videoRef.current.pause();
    // videoRef.current.remove(); // 삭제 기능
  };

  return (
    <div className="App">
      <div>
        <button onClick={playVideo}>Play</button>
        <button onClick={pauseVideo}>Pause</button>
      </div>
      <video ref={videoRef} width="320" height="240" controls>
        <source
          type="video/mp4"
          src="https://player.vimeo.com/external/544643152.sd.mp4?s=7dbf132a4774254dde51f4f9baabbd92f6941282&profile_id=165"
        />
      </video>
    </div>
  );
}

🐟 current.contains(e.target) 예제

ref.current.contains(e.target)는
리액트 컴포넌트의 특정 영역 외 클릭 감지를 위해 사용한다.

const outModalView = useRef();
const [isOpen, setIsOpen] = useState(false);

  useEffect(() => {
    const clickOutside = (e) => {
      // isOpen이 true고 useRef.current이면서
      // outModalView의 html element에 이벤트가 발생한
      // html element가 포함되어 있지 않을 경우
      if (isOpen && outModalView.current && !outModalView.current.contains(e.target)) {
        setIsOpen(false);
      }
    };

    document.addEventListener("mousedown", clickOutside);

    return () => {
      // 이벤트 지우기
      document.removeEventListener("mousedown", clickOutside);
    };
  }, [isOpen]);
 
return ... 
// ModalView가 아닌 밖의 창을 누르면 setIsOpen(false)가 된다.
<ModalView ref={outModalView}> ...

👉 forwardRef, callbackRef 사용법 보러가기
👉 (공식문서)Ref와 DOM 보러가기

profile
🐾

0개의 댓글