Jun 개발노트

useRef 활용법

2020-09-07

UseRef의 current?

  1. 정의

    • 컴포넌트 내에서 mutable한 객체를 만들어 사용 할 수 있다.
    • ref Object의 추가된 값은 current 키의 값으로 업데이트된다.
    • mutable한 객체는 자바스크립트 Heap객체처럼 사용가능하다
    • React는 상태가 변경되면 렌더링이 되고나서 상태의 값을 알 수 있기떄문에 불필요한 렌더링을 막을수 있다.
    • 컴포넌트 안에서 조회 및 수정 할 수 있다(생명주기 포함)
    • 리엑트는 변경상태를 감지하지 않는다.(값 - mutable object)이 변경되도 리렌더링 되지 않는다.)
  2. 사용법

    1. DOM 선택
      • input태그의 ref property에 넣으면 ref.current 객체안에 input에 대한 속성이 입력된다.
      • ref.current안에는 input에 대한 이벤트 / 속성이 있어 focus()같은 처리를 할 수 있다.
      const Focus = () => {
        const InpuRef = useRef();
        const getFocus = () => {
          InpuRef.current.focus();
        }
        return(
          <>
            <button onClick={getFocus}>Focus</button>
            <input type="text" ref={InpuRef}/>
          </>
        )
      }
      
    2. 클래스의 Instance filed 처럼 사용
      • useRef()의 매개변수로 하나의 객체를 초기화해서 사용가능(current 키의 value)
      • useRef()의 current 객체에 접근해서 언제든지 조회/수정/입력이 가능하다
      • 리엑트는 이러한 ref객체의 변경을 감지하지 못한다.
      • setTimeout, setInterval을 통해서 만들어진 id
      • 외부 라이브러리를 사용하여 생성된 인스턴스(socket)
      • 스크롤 위치에서 사용된다.
      //setTimeout / setInterval 사용
         function Timer() {
           const intervalRef = useRef();
         
           useEffect(() => {
             const id = setInterval(() => {
             });
             intervalRef.current = id;
             return () => {
               clearInterval(intervalRef.current);
             };
           });
         
         }
      // 외부 라이브러리 사용
        const socket = useRef();
      
        useEffect(() => {
          socket.current = io.connect("http://localhost:8000");
          navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
            setStream(stream);
            if (userVideo.current) {
              userVideo.current.srcObject = stream;
            }
          })
          socket.current.on("yourID", (id) => {
          })
        }, []);
      
  3. 주의사항

    • 렌더링 중에 ref를 설정하면 사이드 이펙트 발생
    • useRef()의 initialState는 생성자를 호춣하면 매번 ref객체가 생김
      function Image(props) {
        // ⚠️ 렌더링 마다 계속해서 생성
        const ref = useRef(new IntersectionObserver(onIntersect));
      }
      
      function Image(props) {
        const ref = useRef(null);
      
        // ✅ 한번만 생성
        function getObserver() {
          if (ref.current === null) {
            ref.current = new IntersectionObserver(onIntersect);
          }
          return ref.current;
        }
      
        // 필요시 getObserver() 호출
      }