본문 바로가기
팀프로젝트_기록일지/React_이정환_React내부최적화

(11).이정환_react.js강의_컴포넌트 중 불필요한 재렌더링방지 =>React.memo() , 불필요한 함수 재생성 => useCallback()

by 코잼민 2025. 1. 18.

개발자 도구창을 열고, 한 item항목의 checkBox 클릭으 반복적으로 하면, 어떤 부분이 재랜더링 되고있는 지를 알 수 있다.

아래의 사진은 checkBox를 계속 누를 시, 모든 컴포넌트에서 재랜더링이 되고 있다는 것을 알 수 있다. // 불필요한 재랜더링이 발생 중이다.

○ 목표 : 특정 item의 isDone을 checkBox로 반복적으로 변경 시,

- Header가 재랜더링 되지 않도록 막기

- 바뀌는 특정 item만 재랜더링되고, 나머지 item들은 재랜더링이 되지 않도록 셋팅해보기

1_ Header 컴포넌트의 재랜더링 막기 :

- 순서1_ import로 memo 메소드 라이브러리 등록

- 순서2_ export default 에 컴포넌트를 memo(Header)로 변경

- Header.js

import "./Header.css";
import { memo } from "react";

function Header() {
  console.log("Header 렌더링!!");//실험용 출력문

  return (
    <div className="Header">
      <h4>오늘은📅</h4>
      <h1>{new Date().toDateString()}</h1>
    </div>
  );
}

export default memo(Header);

2_ 변경 이외의 item은 재랜더링되지 않도록 하기 => memo(콜백함수) + 특정 props만 변경시에만, 재랜더링 되도록 하기

방법이 2가지 있는데

- 방법1_ 불필요한 함수 재생성,호출 방지 : useCallBack

- ✅방법2_ "memo"를 이용하여, item의 데이터의 프로퍼티 중 변경된 항목이 있다면, 재랜더링 하기

알아야 할 개념 : memo 메소드 매개인자1 : 컴포넌트 , 매개인자2 : ✅콜백 함수 / return : true , false
- true => 재랜더링 X
- false => 재랜더링 O
export default memo(TodoItem , (prevProps , nextProps)=>{
    if(preProps.isDone !== nextProps.isDone) return false;
    //isDone만 검사하여, 변경됐을 시, 재랜더링
    return true
    //나머지는 신경 쓰지 말고, 재랜더링 X

});
-TodoItem.js 코드 :
import { memo } from "react";
import "./TodoItem.css";

function TodoItem({ item, onUpdateItem, onDeleteItem }) {
  const { id, isDone, content, date } = item;

  const onChangeIsDone = () => {
    onUpdateItem(id);
  };

  const onClickDelete = () => {
    onDeleteItem(id);
  };

  console.log(`item ${id}는 재랜더링!!`); //어떤 item이 재랜더링 되는지 확인용 출력

  return (
    <div className="TodoItem">
      <input type="checkbox" checked={isDone} onChange={onChangeIsDone} />
      <p className="TodoItem-title">{content}</p>
      <p className="TodoItem-date">{date.toLocaleDateString()}</p>
      <button onClick={onClickDelete}>삭제</button> 
    </div>
  );
}

export default memo(TodoItem, (prevProps, nextProps) => {
  if (prevProps.item.isDone !== nextProps.item.isDone) return false;

  return true;
});

3_ useCallBack()로 Mount상태일 때만 함수들을 딱한번만 생성하고, 그 외에는 불필요한 함수 생성 막기 :

- 순서1_ import로 useCallBack 메소드 라이브러리 등록

- 순서2_App컴포넌트의 삭제 , 추가 , 수정의 메소드를 useCallback(()=>{ 함수 구현부 내용} , []); 로 수정

 

- App.jsx

const onCreateItem = useCallback((content) => {
    console.log("Create Item!!");
    dispatch({
      type: "CREATE",
      data: {
        id: ++idRef.current,
        isDone: false,
        content: content,
        date: new Date(),
      },
    });
  }, []);

  const onUpdateItem = useCallback((targetID) => {
    console.log("Update Item!!");
    dispatch({
      type: "UPDATE",
      data: targetID,
    });
  }, []);

  const onDeleteItem = useCallback((targetID) => {
    console.log("Delete Item!!");
    dispatch({
      type: "DELETE",
      data: targetID,
    });
  }, []);

- TodoItem.jsx

export default memo(TodoItem);
// export default memo(TodoItem, (prevProps, nextProps) => {
//   if (prevProps.item.isDone !== nextProps.item.isDone) return false;

//   return true;
// });

○ 출력 결과 : 변경된 item만 재 랜더링 된다는 것을 알 수 있다. (props 비교 없이 , 오직 메소드() 생성으로 재랜더링 판단한 것이다.)

 

4_ 한 프로젝트를 만들 때, 최적화 단계는? 

- 순서1_기능 구현 : useState , useRef , useReducer(얘는 코드 가독성에 대한 최적화 같음)

- 순서2_모든 기능을 구현 후, useMemo(어떤 값을 기준으로  렌더링 되도록 하는 메소드) ,React.memo(컴포넌트 메소드), useCallback(함수 재생성 방지 최적화)

 

5_ 주로 최적화가 필요한 대상의 우선순위

=> 함수 => 변하는 props의 프로퍼티들 => 컴포넌트