본문 바로가기
Library-Framework/React

[React] DOM 선택 시, querySelector 대신 useRef 사용하기

by 그랴 2022. 10. 24.

문제 상황

현재 사용자가 위치한 페이지에 따라 메뉴 탭의 색을 바꿔주고 싶었다.

이를 구현하기 위해 내가 생각한 방법은 다음과 같다.

1. 현재 위치한 페이지의 링크 끝에 적힌 탭 이름을 가져온다.

2. 탭 이름을 메뉴 탭의 이름과 비교한다.

3. 탭 이름이 메뉴 탭의 이름과 일치한다면, 색을 바꿔준다.

 

오류

TypeError: Cannot read properties of null (reading 'style')

 

원인

HTML이 렌더링되기 전에 JS가 작동되었기 때문에, style 속성값을 읽어올 수 없어 발생한 문제였다.

 

해결 방법

리액트에서는 DOM을 선택할 때, querySelector가 아닌 useRef를 사용한다고 한다.

 

useRef()

  • .current 프로퍼티로 전달된 인자(initialValue)로 초기화된 변경 가능한 ref 객체를 반환한다.
  • JS의 DOM Selector(querySelector, getElementByID)와 비슷하다.
  • useRef 객체 생성 → 선택하고 싶은 DOM에 ref값으로 객체 넣기 → 객체를 통해 수행하고 싶은 작업 설정
  • 모든 컴포넌트는 reference element를 가진다. (리액트에서 해당 컴포넌트를 참조함)
  • ref = { 변수명 }
  • 이 외에도, 현재 저장하고 싶은 값을 re-rendering 없이 저장하고 싶을 때도 사용할 수 있다.

 

 

즉 DOM 선택 시, querySelector 말고 useRef()를 사용해주면 된다. id 대신 ref를 적용해주면 된다.
const KeyNav = () => {
  let currUrl = window.document.location.href;
  let currKeyWord = currUrl.substring(29);

  const spicy = useRef();
  const sweet = useRef();
  const sour = useRef();
  const nutty = useRef();
  const salty = useRef();

  useEffect(() => {
    changeColor();
  });

  const changeColor = () => {
    if (currKeyWord === "spicy") {
      spicy.current.style.color = "#BC1D1B";
    } else if (currKeyWord === "sweet") {
      sweet.current.style.color = "#BC1D1B";
    } else if (currKeyWord === "sour") {
      sour.current.style.color = "#BC1D1B";
    } else if (currKeyWord === "nutty") {
      nutty.current.style.color = "#BC1D1B";
    } else if (currKeyWord === "salty") {
      salty.current.style.color = "#BC1D1B";
    }
  };

  return (
    <Nav>
      <Link
        to="/spicy"
        style={{
          fontWeight: "900",
          color: "black",
          textDecorationLine: "none",
        }}
      >
        <span ref={spicy}>매콤 </span>
      </Link>
      <Link
        to="/sweet"
        style={{
          fontWeight: "900",
          color: "black",
          textDecorationLine: "none",
        }}
      >
        <span ref={sweet}>달콤 </span>
      </Link>
      <Link
        to="/sour"
        style={{
          fontWeight: "900",
          color: "black",
          textDecorationLine: "none",
        }}
      >
        <span ref={sour}>새콤 </span>
      </Link>
      <Link
        to="/nutty"
        style={{
          fontWeight: "900",
          color: "black",
          textDecorationLine: "none",
        }}
      >
        <span ref={nutty}>고소 </span>
      </Link>
      <Link
        to="/salty"
        style={{
          fontWeight: "900",
          color: "black",
          textDecorationLine: "none",
        }}
      >
        <span ref={salty}>짧조름 </span>
      </Link>
    </Nav>
  );
};