한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 - 인프런 | 강의
개념부터 독특한 프로젝트까지 함께 다뤄보며 자바스크립트와 리액트를 이 강의로 한 번에 끝내요. 학습은 짧게, 응용은 길게 17시간 분량의 All-in-one 강의!, - 강의 소개 | 인프런...
www.inflearn.com
[React Project: 간단한 일기장(7)] 최적화2 - React.memo
한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 - 인프런 | 강의 개념부터 독특한 프로젝트까지 함께 다뤄보며 자바스크립트와 리액트를 이 강의로 한 번에 끝내요. 학습은 짧게, 응
su-vin25.tistory.com
이어서...
앞서 다룬 useMemo와 React.memo를 통해서 지금까지 만들어온 일기장에 적용하여 최적화를 해보자
그렇기 위해선 어떤 컴포넌트들을 최적화 해야 하는지를 알아야 하기 때문에 우리는
React develop tool의 highlight render기능을 통해 어떤 컴포넌트들이 낭비되고 있는지를 찾아낼 것이다
우선 첫 번째
일기를 삭제하는 행동을 할 때 전혀 상관없는 DiaryEditor 컴포넌트도 리렌더가 된다 이걸 최적화시켜보자
간단하다! DiaryEditor컴포넌트를 React.memo로 감싸주면 된다 하지만 코드가 길면 보기도 별로고 그래서
export default React.memo(DiaryEditor);
export 시키는 것을 React.memo로 묶어주면 같은 역할을 한다 더 간단하게 사용 가능!
하지만 DiaryEditor에서 prop으로 받는 onCreate는 객체이므로 얕은 비교에 들어가서 계속 리렌더가 발생한다
그래서 onCreate함수가 재생성되지 않아야만 한다
그럼 onCreate함수로 넘어가 보자 그럼 앞에서 배웠던 거처럼 useMemo를 사용하면 되는 거 아닌가?
안된다 우리는 onCreate함수 그대로 넘어가길 바라지만 useMemo를 사용하면 값으로 넘어가게 되기 때문이다
여기서 사용될 수 있는 기능이 useCallback이다
useCallback
메모이제이션된 콜백을 반환한다
즉 useMemo처럼 값을 반환하는 게 아닌 콜백함수 그대로 반환해 준다
const onCreate = useCallback((author,content,emotion)=>{
const created_date = new Date().getTime();
const newItem={
author,
content,
emotion,
created_date,
id: dataId.current,
}
dataId.current+=1;
setData([newItem,...data])
},[]);
onCreate 함수를 useCallback으로 감싸주면 된다 그리고 defendency array에는 빈배열을 넣어주자
어라? 새로운 일기를 추가하면 기존의 있던 일기들이 다 없어진다..
이유는 defendency array를 빈배열로 했기 때문에 data가 빈상태로 초기화되기 때문이다
그렇다고 data값을 넣어주면 DiaryEditor가 리렌더가 되어버린다.. 딜레마에 빠진 것이다
이걸 해결하기 위한 방법이 함수형 Update이다
함수형 Update
useState의 setState에 값이 아닌 함수를 전달하는 것
이렇게 setState에 콜백함수로 전달된 함수는 어떤 상황이든 항상 매개변수로 최신의 state만 제공받는 기능을 한다
이렇게 인자로 data를 받아서 아이템을 추가한 데이터를 리턴하는 콜백함수를 setData함수에 전달한다
이렇게 한 면 우리가 defendency array를 빈배열로 해도 항상 최신의 state를 콜백함수의 인자로 받아오게 한다
const onCreate = useCallback((author,content,emotion)=>{
const created_date = new Date().getTime();
const newItem={
author,
content,
emotion,
created_date,
id: dataId.current,
}
dataId.current+=1;
setData((data)=>[newItem,...data])
},[]);
그럼 원래대로 일기가 정상적으로 추가된다
두 번째
일기를 하나만 삭제했는데 나머지 일기 모두가 리렌더링 되는 걸 볼 수 있다
일기가 많으면 많아질수록 성능에 막대한 악영향을 줄 것이다
이에 관련된 DiaryItem으로 가보자
prop으로 이렇게 받는다 우리는 변화불가능한 데이터들을 뺀 content, onDelete, onEdit을 최적화해볼 것이다
우선 DiaryItem을 React.memo로 감싸주지
onDelete와 onEdit 함수 또한 앞서 onCreate함수처럼 useCallback과 함수형 update를 통해 최적해 해준다
const onDelete =(targetId)=>{
const newDiaryList= data.filter((it)=>it.id!==targetId);
setData(newDiaryList);
}
const onEdit =(targetId,newContent)=>{
setData(
data.map((it)=>it.id===targetId?{...it,content:newContent}:it)
)
}
↓
const onDelete = useCallback((targetId)=>{
setData((data)=>data.filter((it)=>it.id!==targetId));
},[])
const onEdit = useCallback((targetId,newContent)=>{
setData(()=>
data.map((it)=>it.id===targetId?{...it,content:newContent}:it)
)
},[])
이렇게 일기장 프로젝트의 최적화가 완료되었다!
..💬
useEffect, useMemo, useCallback 비슷하면서도 쓰이는 데가 너무 달라 적절히 잘 써야겠다
그래고 객체는 얕은 비교, 그래서 함수형 update를 해줘야 한다는 것 휴
'개발🐕 > React' 카테고리의 다른 글
[React Project: 간단한 일기장(完)] 컴포넌트 트리에 데이터 공급하기- Context (0) | 2023.01.07 |
---|---|
[React Project: 간단한 일기장(9)] 로직 분리하기 -useReducer (0) | 2023.01.06 |
[React Project: 간단한 일기장(7)] 최적화2 - React.memo (0) | 2023.01.05 |
[React Project: 간단한 일기장(6)] 최적화1 - useMemo (0) | 2023.01.05 |
[React] 리액트 useEffect? feat. Lifecycle (+예제코드) (1) | 2023.01.04 |