최적화에는 직접 코드를 눈으로 하나하나 보고 판단하는 정적인 분석과정이 있고, 프로그램 도구를 이용해 찾아내는 동적 분석이 있다
근데 난 아직 바보니까 동적 분석을 이용해보기로 함..ㅎ
컴포넌트 탭에서 Highlight updates when components render
부분을 체크해 찾아보도록 하자
이 기능은 뭔가가 바뀌었을 때 어떤 state들이 변화가 되는지 보여주는 기능이다.
날짜 변화시에 상단에 필터와 새 글쓰는 버튼이 계속 렌더가 되고 있는 모습을 볼 수 있음
근데 사실 월을 바꾼다고 해서 그부분이 새로 렌더 될 필요가 없다.
그 부분은 controlMenu로, Home컴포넌트에서 일단 increaseMonth, decreaseMonth로 날짜가 바뀌고, 또 그 자식 요소인 DiaryList 컴포넌트 안에 있는 controlMenu가 계속 렌더링 되는 것이다.
controlMenu를 React.memo로 감싸준다.
const ControlMenu = React.memo(({ value, onChange, optionList }) => {
return (
<select
className="ControlMenu"
value={value}
onChange={(e) => onChange(e.target.value)}
>
{optionList.map((it, idx) => (
<option key={idx} value={it.value}>
{it.name}
</option>
))}
</select>
);
});
컴포넌트를 React.memo로 감싸면, 즉 React.memo 함수의 인자로 전달하면, 강화된 컴포넌트를 돌려주는 고차 컴포넌트이다.
즉, 전달받는 prop의 값이 바뀌지 않으면 렌더링 되지 않는다.
DiaryList.js
const [sortType, setSortType] = useState("latest");
const [filter, setFilter] = useState("all");
이 useState를 만든 상태변화함수는 렌더링이 일어났을 때도 동일한 id를 보장한다.
useCallback이 이미 적용된 친구라고 생각하면 됨.
const handleSortType = (sortType) => {
setSortType(sortType);
};
const handleFilter = (filter) => {
setFilter(filter);
};
근데 이렇게 생성한 함수는, 컴포넌트가 리렌더링 될 때 다시 생성이 된다.
그래서 리액트 메모가 생각했을 때 다른 프롭으로 인식함.
그러니 굳이 핸들링을 한번 거치지 않고, 꼭 필요한 경우가 아니라면 useState로 하면 좋다.
최신순, 오래된 순을 동작할 때, 필요한 부분만 바뀌면 되는데 모두가 리렌더링이 되거나,
좋은 감정, 안 좋은 감정 등을 선택할 때도 바뀔 부분이 없는데 리렌더링이 되고 있다.
이는 DiaryList의 state가 바뀌었기 때문에 리렌더링 되고,
그로 인해 자식 컴포넌트인 DiaryItem이 렌더링 되고 있기 때문
근데 이렇게 특히! 이미지나 동영상, 긴 텍스트를 포함하고 있는 item은 양이 많아지면 위험하기 때문에 어여어여 만져주어야함
DiaryItem.js
export default React.memo(DiaryItem);
이렇게 해주면 간단히 해결 (react import 해주는 건 생략한당)
content를 쓸 때마다 emotion 부분도 계속 렌더가 되는 걸 볼 수 있음
DiaryEditor 가 갖고 있는 state가 변화되니,
자연스럽게 그 자식컴포넌트들이 렌더링이 되고 있는 것
EmotionItem.js
export default React.memo(EmotionItem);
그리고 EmotionItem에서 재사용되고 있는 함수 onClick도 찾아가줌.
DiaryEditor.js
const handleClickEmote = useCallback((emotion) => {
setEmotion(emotion);
}, []);
이 부분은 useCallback을 써 준다.
그러면 작성 시에 감정들이 렌더링이 안되는 걸 볼 수 있음~
useCallback 과 memo의 적절한 사용 잘봤습니다 !