[React] React.memo

삽질 저장소·2022년 6월 21일
0

React

목록 보기
1/1

React에서는 부모 컴포넌트가 리렌더되면 자식 컴포넌트들도 리렌더된다. 당연한 일로 볼 수도 있지만 프로젝트의 규모거 커진다면 자식 컴포넌트들의 불필요한 리렌더는 성능에 악영향을 줄 것이다.

부모 state={count, text}
자식 1 prop={count}자식 2 prop={text}

위의 예시에서 부모 컴포넌트인 App은 state로 count, text를 가지고 있고 각 state를 자식1과 자식2에게 넘겨준다.

만약 count가 업데이트된다면 3가지 컴포넌트 모두 리렌더된다. 이때 TextView는 text가 업데이트되지 않았는데도 리렌더되므로 불필요한 리렌더가 진행된다.

이를 막기 위해서는 자식 컴포넌트가 받는 prop이 업데이트 될 때만 리렌더를 하는 조건을 걸어주면 된다. 예를들어 count가 업데이트 됐을때는 App과 CountView만 리렌더 해주는 것이다.

이러한 기능을 도와주는 기능이 React.memo다. React.memo는 특정 컴포넌트를 감싸서 새로운 컴포넌트로 만들어주는 함수의 역할을 한다.

import React, { useState, useEffect } from "react";

const TextView = ({ text }) => {
  useEffect(() => {
    console.log(`update::Text:${text}`);
  });
  return <div>{text}</div>;
};
const CountView = ({ count }) => {
  useEffect(() => {
    console.log(`update::Count:${count}`);
  });
  return <div>{count}</div>;
};

const OptimizeTest = () => {
  const [count, setCount] = useState(1);
  const [text, setText] = useState("");

  return (
    <div style={{ padding: 50 }}>
      <div>
        <h2>count</h2>
        <CountView count={count} />
        <button
          onClick={() => {
            setCount(count + 1);
          }}
        >
          +
        </button>
      </div>
      <div>
        <h2>text</h2>
        <TextView text={text} />
        <input
          type="text"
          value={text}
          onChange={(e) => {
            setText(e.target.value);
          }}
        />
      </div>
    </div>
  );
};

export default OptimizeTest;

위의 코드는 앞서 말한 상황을 코드로 만든것이다. 해당 코드를 처음 실행하면 콘솔에

update::Count:1
update::Text:

라고 출력된다. 그다음 count를 바꾸기 위해 +버튼을 눌러 count의 상태를 변화시키면

update::Count:2
update::Text:
update::Count:3
update::Text:

이렇게 상태가 변하지 않은 Text도 함께 출력되는 것을 볼 수 있다. 이러한 현상을 해결하기 위해서

import React, { useState, useEffect } from "react";

//React.memo 추가
const TextView = React.memo(({ text }) => {
  useEffect(() => {
    console.log(`update::Text:${text}`);
  });
  return <div>{text}</div>;
});

//React.memo 추가
const CountView = React.memo(({ count }) => {
  useEffect(() => {
    console.log(`update::Count:${count}`);
  });
  return <div>{count}</div>;
});

const OptimizeTest = () => {
  const [count, setCount] = useState(1);
  const [text, setText] = useState("");

  return (
    <div style={{ padding: 50 }}>
      <div>
        <h2>count</h2>
        <CountView count={count} />
        <button
          onClick={() => {
            setCount(count + 1);
          }}
        >
          +
        </button>
      </div>
      <div>
        <h2>text</h2>
        <TextView text={text} />
        <input
          type="text"
          value={text}
          onChange={(e) => {
            setText(e.target.value);
          }}
        />
      </div>
    </div>
  );
};

export default OptimizeTest;

이렇게 React.memo로 컴포넌트를 감싸주게 되면 해당 컴포넌트는 자신이 가지고있응 prop이 업데이트 될 때만 리렌더를 진행하게된다. 즉, 컴포넌트에 같은 props가 들어온다면 컴포넌트 렌더링 과정을 스킵하고 마지막에 렌더링된 결과를 재사용한다.

React.memo는 props가 변경됐는지 여부만 확인한다.

0개의 댓글