All'alba vincerò

At dawn, I will win!

React/한입 리액트

memo: 최적화된 컴포넌트로 만드는 React Hook

나디아 Nadia 2024. 4. 2. 21:35

 

 

 

 

📌 memo 

: 컴포넌트를 인수로 받아 최적화된 컴포넌트로 만들어 반환

 

  • React의 내장 함수
  • 얕은 복사 ('==='로 비교, 주소값 X)

 

  • 최적화된 컴포넌트는 props를 기준으로 메모이제이션 된다.

 

 

  • 메모이즈드 컴포넌트(Memoized Componenet, 최적화된 컴포넌트)는
    부모 컴포넌트가 리렌더링 되더라도, 자신이 받는 props가 바뀌지 않으면 다시는 리렌더링이 실행되지 않도록 함 
    👉 불필요한 리렌더링 방지

 

 

 

 

고차 컴포넌트(HOC, Higher Order Component)
: 컴포넌트를 인수로 받아 해당 컴포넌트에 추가적인 기능(최적화, 메모이제이션)을 덧붙여 새로운 컴포넌트를 반환해주는 컴포넌트

 

 


 

 

📌 memo 사용하기

📍 memo 불러오기

import { memo } from "react";



 

 

📍 memo 호출하기

 

memo(컴포넌트[, 콜백 함수]);

  • 컴포넌트: 최적화하고 싶은 컴포넌트
  • 컴포넌트 외부에 memo 호출
  • 콜백 함수는 생략 가능
export default memo(Header);

 

 

 


 

 

📌 컴포넌트 최적화하기

 

📍 Header.jsx는 렌더링 될 필요가 없음 👉 최적화된 컴포넌트로 바꾸기

최적화 X      최적화 O

  • 인수로 받은 Header 컴포넌트를 props가 변경되지 않았을 때에는 리렌더링 하지 않도록 최적화해서 반환해줌
  • 메모이즈드 컴포넌트를 반환
import { memo } from "react";
import "./Header.css";

const Header = () => {
    return (
    <div className="Header">
        <h2>오늘은 📆</h2>
        <h1>{new Date().toDateString()}</h1>
        {/* // Date 객체 생성 후 String으로 변환 */}
    </div>
    )
}

export default memo(Header);

 

 

 



📍 값이 바뀌는 하나의 TodoItem만 렌더링하기

최적화 X

 

  • TodoItem 컴포넌트에 전달되는 onUpdate, onDelete가 App 컴포넌트가 리렌더링 될 때마다 새롭게 생성되어 전달됨 
    👉 함수가 매번 새롭게 전달될 때마다 다른 주소값을 가지기 때문에 다른 값으로 인지함
    👉 memo 메서드는 props가 바뀌었다고 판단
const TodoItem = ({id, isDone, content, date, onUpdate, onDelete}) => {



  • memo(TodoItme)은 리렌더링이 발생할 때마다 현재의 props와 과거의 props를 비교, 두 개의 props가 같은 값인지 다른 값인지를 판단해서 TodoItem 컴포넌트를 리렌더링할 지 말 지를 결정한다.
    👉 memo는 얕은 복사를 하기 때문에 객체 타입의 값은 무조건 서로 다른 값이라고 판단한다.  

 

 

 

📌 객체 타입의 최적화 방법 2가지

 

방법 1. 

useCallback 사용하기

: 리렌더링 되더라도 다시 생성되지 않게 방지하는 방법


방법 2.

TodoItem의 memo 함수 안에 두 번째 인수로 콜백 함수를 추가하여 커스터마이징 

: 컴포넌트가 리렌더링 될 때마다 해당 컴포넌트에 과거의 props와 현재의 props를 전달하여 함수의 반환값에 따라 props가 바뀌었는지를 판단

  • {id, isDone, content, date}가 변했을 때만 리렌더링 하면 됨
export default memo(TodoItem, (prevProps, nextProps)=>{
    // 함수의 반환값에 따라 props가 바뀌었는지를 판단
    // True -> props 바뀌지 않음 -> 리렌더링 X
    // false -> props 바뀜 -> 리렌더링 O
    if (prevProps.id !== nextProps.id) return false;
    if (prevProps.isDone !== nextProps.isDone) return false;
    if (prevProps.content !== nextProps.content) return false;
    if (prevProps.date !== nextProps.date) return false;

    return true; // 위에 걸리지 않으면 true
});

 

 

 


 

 

출처

한입 크기로 잘라먹는 리액트