useMemo
이미 계산한 연산 결과를 기억해뒀다가 동일한 계산을 시킬 때, 기억해둔 데이터를 반환하는 방법
이렇게 기억해두는 것을 memoization이라고 한다.
useMemo는 return을 가지고 있는 함수를 감싸 사용한다.
useMemo(() => {}, [])
useEffect와 같이 콜백 함수에 코드를 적고, 의존성 배열에 넣는 값이 변하지 않으면 다시 연산하지 않는다.
즉 의존성 배열에 넣는 값이 변할 때만 다시 연산한다.
일기장 어플리케이션을 만들고 있는데, 일기 하나의 내용을 수정하는 액션을 할 때 모든 게 리렌더링 되었다.
const getDiaryAnalysis = () => {
console.log("일기 분석 시작");
const goodCount = data.filter((it) => it.emotion >= 3).length;
const badCount = data.length - goodCount;
const goodRation = (goodCount / data.length) * 100;
return { goodCount, badCount, goodRation };
};
// 구조 분해 할당으로 다시 받기
const { goodCount, badCount, goodRation } = getDiaryAnalysis;
// onCreate로 setData에 데이터 추가
// diaryList에서 수정된 데이터 초기값을 받아옴
return (
<div className="App">
<DiaryEditor onCreate={onCreate} />
<div> 전체 일기: {data.length} </div>
<div> 기분 좋은 일기 개수: {goodCount} </div>
<div> 기분 나쁜 일기 개수: {badCount} </div>
<div> 기분 좋은 일기 비율: {goodRation} </div>
<DiaryList diaryList={data} onRemove={onRemove} onEdit={onEdit} />
</div>
);
getDiaryAnalysis 함수의 경우 일기 하나의 내용을 수정한다고 해도 전혀 영향 받을 것이 없다.
그럼에도 다시 렌더링 되면서 비효율적으로 연산을 하고 있었다.
이를 방지하기 위해 getDiaryAnalysis 함수에 useMemo를 래핑해주었다.
해당 함수는 오로지 삭제, 즉 data.length가 변화할 때만 다시 그려지면 되는 것이다.
따라서 의존성 배열에 data.length를 넣어주면, 일기를 새로 추가하거나 삭제하는 것과 같이 data.length가 변화할 때만 해당 함수를 다시 리렌더링 해 기분 좋은 일기 개수, 기분 나쁜 일기 개수 등을 연산하게 만든다.
const getDiaryAnalysis = useMemo(() => {
console.log("일기 분석 시작");
const goodCount = data.filter((it) => it.emotion >= 3).length;
const badCount = data.length - goodCount;
const goodRation = (goodCount / data.length) * 100;
return { goodCount, badCount, goodRation };
}, [data.length]);
그런데 이렇게 하고 나면 getDiaryAnalysis가 not function이라고 에러 메세지가 뜬다.
useMemo로 감싼 함수는 더 이상 함수가 아니라 함수의 반환 값을 들고 있는 변수(메모이제이션된 객체)가 되어 버린다.
useMemo 안에서 익명 화살표 함수를 호출해 이미 내부 로직을 실행한 상태이기 때문이다.
하지만 구조 분해 할당을 사용하면 메모이제이션 된 객체 안의 속성들을 개별 변수에 할당할 수 있다.
이렇게 getDiaryAnalysis가 가진 변수들을 goodCount, badCount, goodRation으로 할당해 받으면 된다.
const { goodCount, badCount, goodRation } = getDiaryAnalysis;
**참고
'⚛️ React > 💭 한 입 크기 React' 카테고리의 다른 글
[React] React.createContext로 Props Drilling 방지하기 (0) | 2023.07.26 |
---|---|
[React] useReducer로 상태 변화 로직을 분리하기 (0) | 2023.07.26 |
[React] React.memo로 컴포넌트 재사용하기 (0) | 2023.07.26 |
[React] 리액트의 생애주기 (Mount, Update, Unmount) (0) | 2023.07.25 |
[React] state/setState 효율적으로 작성하기 (0) | 2023.07.24 |