요즘 교육때 들었던 유데미 강의 '한입 크기로 잘라먹는 리액트'를 다시 듣고있다.
오늘 들었던 강의 중 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씩 플러스되어 작동하는 것을 볼 수 있었다.

'React' 카테고리의 다른 글
| 리액트 useState 렌더링 관련 알게 된 것들 : 객체 상태 관리, 상태의 초기 값 (0) | 2024.05.06 |
|---|---|
| [한입리액트] 최적화 : useMemo, React.memo, useCallback, useReducer, context API (0) | 2023.10.18 |
| [React-Query] 2. useMutation 사용하기(공부중...) (0) | 2023.06.27 |
| [React-Query] 2. 리액트쿼리 특징과 useQuery 사용하기 (0) | 2023.06.01 |
| [React-Query] 1. 리액트쿼리 들어가기 전 Axios 알아보기 (0) | 2023.05.31 |