6-13. 최적화 4(완) (프로젝트 최적화 완료)
2022. 7. 7. 16:18ㆍReact/한입 크기로 잘라 먹는 리액트(React.js)
각 일기 하나씩을 삭제할때마다 모든 일기가 rerendering하는 것을 볼 수 있다.
현재는 text로만 이루어졌지만 이미지나 동영상으로 이루어질 경우 엄청난 시간이 소요될 것으로 예상이된다.
우선 DiaryItem를 React.memo로 감싸고,
useEffect로 렌더링할때마다 출력하도록하면 다음과같이 출력됨을 알수 있다.
더보기
import React, { useEffect, useRef, useState } from "react";
const DiaryItem = ({
onEdit,
onRemove,
id,
author,
content,
created_date,
emotion,
}) => {
useEffect(() => {
console.log(`${id}번째 아이템 렌더`);
});
const [isEdit, setIsEdit] = useState(false);
const toggleIsEdit = () => setIsEdit(!isEdit);
const [localContent, setLocalContent] = useState(content);
const localContentInput = useRef();
const handleRemove = () => {
if (window.confirm(`${id}번째 일기를 정말 삭제하시겠습니까?`)) {
onRemove(id);
}
};
const handleQuitEdit = () => {
setIsEdit(false);
setLocalContent(content);
};
const handleEdit = () => {
if (localContent.length < 5) {
localContentInput.current.focus();
return;
}
if (window.confirm(`${id}번째 일기를 수정하시겠습니까?`)) {
onEdit(id, localContent);
toggleIsEdit();
}
};
return (
<div className="DiaryItem">
<div className="info">
<span className="author_info">
작성자 : {author} | 감정: {emotion}
</span>
<br />
<span className="date">{new Date(created_date).toLocaleString()}</span>
</div>
<div className="content">
{isEdit ? (
<>
<textarea
ref={localContentInput}
value={localContent}
onChange={(e) => setLocalContent(e.target.value)}
/>
</>
) : (
<>{content}</>
)}
</div>
{isEdit ? (
<>
<button onClick={handleQuitEdit}>수정 취소</button>
<button onClick={handleEdit}>수정완료</button>
</>
) : (
<>
<button onClick={handleRemove}>삭제하기</button>
<button onClick={toggleIsEdit}>수정하기</button>
</>
)}
</div>
);
};
export default React.memo(DiaryItem);
DiaryItem은 React.memo로 감싼다고해서 최적화가 되지는 않는다.
onEdit과 onRemove는 onCreate처럼 데이터 state가 변화되면 rerendering할 수 밖에 없기 때문이다.
그래서 onCreate처럼 onEdit과 onRemove를 최적화 해보자.
onRemove
const onRemove = (targetId) => {
// filter 기능을 통해 그 부분만 빼고 출력 된다.
const newDiaryList = data.filter((it) => it.id !== targetId);
setData(newDiaryList);
};
에서 아래와 같이 변환
const onRemove = useCallback((targetId) => {
// filter 기능을 통해 그 부분만 빼고 출력 된다.
setData((data) => data.filter((it) => it.id !== targetId));
}, []);
data 파라미터에 최신 데이터가 전달이 되기 때문에, 인자부분을 사용해아한다.
onEdit
const onEdit = (targetId, newContent) => {
setData(
data.map((it) =>
it.id === targetId ? { ...it, content: newContent } : it
)
);
};
에서 아래와 같이 변환
const onEdit = useCallback((targetId, newContent) => {
setData((data) =>
data.map((it) =>
it.id === targetId ? { ...it, content: newContent } : it
)
);
}, []);
이렇게 진행하고 글을 삭제하면 rerendering되지 않아 console에 아무것도 찍히지 않게 된다.
이전에는 0부터 모든 컴포넌트가 rerendering되었었는데 아무것도 렌더링 되지 않는다.
글을 추가한다면 아래와 같이 추가된 부분만 console로 출력된다.
'React > 한입 크기로 잘라 먹는 리액트(React.js)' 카테고리의 다른 글
6-15. 컴포넌트 트리에 데이터 공급하기 (Context API) (0) | 2022.07.21 |
---|---|
6-14. 복잡한 상태변화 로직분리 (useReducer) (0) | 2022.07.07 |
6-12. 최적화 3 (컴포넌트 & 함수 재사용하기) (0) | 2022.07.07 |
6-11. 최적화 2 - 컴포넌트 재 사용 (0) | 2022.07.06 |
6-10. 최적화1 - 연산 결과 재사용(useMemo) (0) | 2022.07.06 |