React

[한입리액트] useRef : 컴포넌트가 리렌더링 되더라도 값이 초기화되지않고 유지시키고 싶을 때 사용

hyriver(강화영) 2023. 7. 27. 14:51

요즘 교육때 들었던 유데미 강의 '한입 크기로 잘라먹는 리액트'를 다시 듣고있다.

오늘 들었던 강의 중 useRef 관련해서 새롭게 알게된 것이 있어 정리해보려고 한다.

 

강의 내용은 리액트로 다이어리를 만드는 것이고,

현재 useState를 사용하여 data라는 배열에 일기를 추가하는 방식을 사용하고 있다.

 

최상위컴포넌트인 App 컴포넌트에 일기를 작성할 수 있는 <DiaryEdior> 컴포넌트가 있고,

이 작성한 일기들을 하단에 보여주는 <DiaryList> 컴포넌트가 있다.

 

App 컴포넌트에서는 useState를 사용하여 data라는 배열 상태에 일기를 추가하도록 하고있다.

App 컴포넌트는 이렇게 생겼다.

function App() {
  const [data, setData] = useState([]);
  const dataId = useRef(0);

  //일기 아이템을 추가하는 함수
  const onCreate = (author, content, emotion) => {
    const created_data = new Date().getTime(); //시간을 밀리세컨드로
    const newItem = {
      author,
      content,
      emotion,
      created_data,
      id: dataId.current, //0
    };
    dataId.current += 1;
    setData([newItem, ...data]); //새로운 일기를 배열 제일 앞에 오도록
  };
  console.log(data);

  return (
    <div className="App">
      <DiaryEditor onCreate={onCreate} />
      <DiaryList diaryList={data} />
    </div>
  );
}

export default App;

 

내가 궁금했던 것은 'dataId를 왜 useRef로 관리를 해야할까?' 였다.

그냥 let으로 선언을 하면 되지 않을까? 라고 생각해서 이 dataId를 let으로 선언하고, 프로젝트를 실행했다.

 

일기 하나를 저장하는건 성공

 

그런데 두번째 일기를 저장하니 경고가 떴다. 키값이 0으로 중복되어 고유하지 않은 키가 있다고 한다.

dataId를

dataId += 1;

을 사용하여 하나씩 증가하는 걸로 설정을 했으나 먹히지 못하는 듯 했다.

 

왜그런가 살펴보니 app컴포넌트가 리렌더링 될 때마다 이 dataId 변수는 계속 0으로 초기화가 된다.

내가 dataId += 1;을 사용하여 dataId값을 1 올려도, 일기를 추가하여 리렌더링 되면 다시 0으로 초기화 되는 것.

 

리액트에서 함수형 컴포넌트는 각 렌더링마다 실행되며, 컴포넌트 함수 내에서 정의된 로컬 변수들은 각 렌더링 마다 재설정된다.

 

그래서 사용하는 것이 useRef이다.

나는 useRef가 DOM요소에 직접 접근할 때 사용하는 것으로만 알고있었는데,

useRef를 사용하여 리렌더링 되어도 값이 변하지 않도록 변수관리를 하는 기능에 대해서는 몰랐다.

useRef는 리렌더링에 영향을 받지 않고, 이처럼 아이템의 id와 같이 고유 식별자로 필요할 때 유용하다.

 

다시 dataId를 useRef로 돌려놓고 실행하니 id가 정상적으로 1씩 플러스되어 작동하는 것을 볼 수 있었다.