ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] useRef는 왜 써야하는가?
    React 2024. 2. 25. 21:57

    useState 장점과 변수의 장점을 합친 것.

    

    useRef란 레퍼런스를 사용하기 위한 훅.

     

    그렇다면 레퍼런스란?

     

    리액트에서 레퍼런스란 특정 컴포넌트에 접근할 수 있는 객체.

     

    레퍼런스 객체에 current 객체가 있음. 이는 현재 참조하고 있는 element.

     

    useRef는 그 값이 변하더라도 렌더링을 발생시키지 않는다.

     

    1. 사용법

     

    const exampleRef = useRef(초기값);

     

     

    2. useRef를 왜 사용해야 하는가?

     

     a. 저장공간으로서의 장점

    값을 저장할 필요가 있는 변수가 있을 때 사용하면 좋음. 단, UI에 보일 필요가 없는 친구들을.

     

    예시로,

    import { useState } from "react";
    
    export default function Example1() {
      const [count, setCount] = useState("");
    
      return (
        <>
          <div>count : {count}</div>
          <button onClick={() => setCount((prev) => prev + 1)}>1씩증가!</button>
        </>
      );
    }

     

    이런 경우에는 count가 버튼 클릭 시 1씩 잘 증가되는 것을 볼 수 있다.

     

    퀴즈)) 그렇다면 변수의 경우엔 어떻게 될까??

     

    import { useState } from "react";
    
    export default function Example1() {
      const [count, setCount] = useState("");
      let 변수 = 0;
      return (
        <>
          <div>count : {count}</div>
          <div>변수 : {변수}</div>
          <button onClick={() => setCount((prev) => prev + 1)}>count 1씩증가!</button>
          <button onClick={() => 변수++}>변수 1씩증가!</button>
        </>
      );
    }

     

     

    답 1. 실습 참고

     

    또한!!

     

    답 2. 실습 참고

     

    이제 useRef를 이용해보자. 

     

      const refCount = useRef(null);
    .
    .
    .
    
          <button onClick={() => console.log('ref', refCount)}>ref를 콘솔로그 찍으면?</button>

     

    우선적으로 useRef에는 어떤 값이 들어가있는가를 확인해보기 위해 콘솔을 찍어 보았다.

     

     

    오호! ref안에는 객체가 들어오고, 그 객체 안에는 current라는 키 값이 있다.

     

      const refCount = useRef(null);
    
    return
          <div>refCount : {refCount.current}</div>
    
          <button onClick={() => refCount.current++}>ref 1씩 증가!</button>
        </>
      );
    }

     

    ref 1씩 증가! 라는 버튼을 클릭해도 화면 ui에는 그려지지 않는다. 

     

    그러나

     

    재렌더링이 일어난 이후에는 증가한 ref값을 볼 수 있을 것이다.

     

    이렇게 useRef는 ui에 보여지지 않지만 값을 저장하는 용도로 사용할 수 있다.

     

    다만, 실무에서 이런 용도로 사용할 일이 많을지는 더 공부해봐야 할 것 같다.

     

     

     

     b. DOM을 선택하는 기능

     

    useRef의 가장 좋은 기능이라고 할 수 있을 것 같다. 

    javascript에서 document.querySelector와 같은 것들을 사용하며 DOM에 접근하고는 했는데,

     

    react를 배우면서 생각해보면, document.querySelector과 같은 것들을 사용한 적이 없었다는 것을 알 수 있을 것이다.

    그러나, 우리는 react에서도 직접적으로 접근해야할 필요성이 있다.

    공식문서에서는 이 경우에 접근하도록 권장한다.

     

    Ref의 바람직한 사용 사례는 다음과 같습니다.

     

     

    Ref와 DOM – React

    A JavaScript library for building user interfaces

    ko.legacy.reactjs.org

     

    간단한 예시로, input창에 버튼 클릭 시 focus 되는 로직을 작성해보자.

     

    function App() {
      const inputRef = useRef(0);
    
      const clickBtn = () => {
        inputRef.current.focus();
      };
    
      return (
        <>
          <input ref={inputRef} type="text" />
          <button onClick={clickBtn}>클릭해봐</button>
    
        </>
      );
    }
    
    export default App;

     

     

    input에 ref라는 속성을 주어 dom에 직접 접근할 수 있다.

    또한 설정해둔 ref (inputRef) 속 current 키값에 focus 속성을 주어 버튼 클릭 시 input에 focus되는 로직을 쉽게 구현할 수 있다.

     

    이번 프로젝트를 통해 useRef의 필요성을 알게되었는데, 이 DOM을 선택할 수 있다는 장점 덕분에 알게되었다.

     

    아이콘 클릭 시 브라우저 기본 input type='time'을 보여줘야 하는데, 처음에 useRef를 사용해야한다는 생각조차 하지 못했었기 때문에, 

     

    그 경험을 공유해보고자 한다.

     

    interface TimePickerProps {
      onSelect: (selectedTime: string) => void;
    }
    
    const TimePicker = ({ onSelect }: TimePickerProps) => {
    
      const clockRef = useRef<HTMLInputElement>(null);
    
      const handleIconClick = () => {
        clockRef.current?.showPicker();
      };
    
    
      return (
        <>
          <S.TextField onClick={handleIconClick}>
            <S.Input
              placeholder='시작 시간을 선택해주세요'
              value={selectedTime}
              onChange={(e) => setSelectedTime(e.target.value)}
            />
          </S.TextField>
          <S.IconField>
            <input
              ref={clockRef}
              type='time'
              id='clock'
              onChange={(e) => handleTimeSelect(e.target.value)}
              style={{ display: 'flex', opacity: 0 }}
            />
            <label htmlFor='clock'>
              <IcUnselectedClock
                style={{ width: '2.4rem', height: '2.4rem' }}
              />
            </label>
          </S.IconField>
        </>
      );
    };
    
    export default TimePicker;

     

    전체 코드를 가져오지는 않고, 일부만 가지고 왔다.

     

    ref를 사용하지 않을 때는, 기본으로 출력되는 input type='time' 이 굉장히 거슬렸고,

    화면 ui에 맞지 않았으며, 같은 팀 디자이너 분들이 이를 가려주기를 원하셨다.

     

    분명히 방법이 있을 것이라고 생각하고 찾아본 결과, useRef를 사용하게 되었다.

    시간을 선택할 수 있는 input에 ref를 만들어주고,

    기본으로 출력되는 input type='time' 을 opacity 0을 주어 안보이게끔 처리한 후에,

    이 DOM에 직접 접근하여 해당 영역 클릭 시 clockRef.current.showPicker()로 브라우저 기본 시간 선택 창을 나타낼 수 있게 하였다.

     

     

    **여기서 showPicker란?

     

    HTMLInputElement.showPicker() 메소드는 input 요소에 대한 브라우저 선택기를 표시합니다.

Designed by Tistory.