본문 바로가기

프론트엔드/Java Script

JavaScript Sec05_8 최적화 2 - 컴포넌트 재사용

React.memo

함수형 컴포넌트에게 업데이트 조건을 걸자


  • 이 경우 부모 컴포넌트가 리렌더 되기 때문에 자식 컴포넌트들이 리렌더 된다. 하지만 count 상태만 변화했기 때문에 TextView는 리렌더 될 필요가 없다.

  • 이렇게 업데이트 조건을 걸어 불필요한 컴포넌트 재사용을 막는다.

React.memo

  • React.memo는 고차 컴포넌트이다.
    • 고차 컴포넌트 : 파라미터로 컴포넌트를 가져와 새 컴포넌트를 반환하는 함수
  • 재사용이 필요한 함수를 React.memo로 감싸준다.

  • 이렇게 React.memo로 감싸면 prop으로 전달된 text가 변하지 않으면 리렌더링을 하지 않게 된다.
const MyComponent = React.memo(function MyComponent(props) {
  /* props를 사용하여 렌더링 */
});
  • 컴포넌트가 동일한 prop을 받아 동일한 결과를 렌더링해낸다면, React.memo를 호출하고 결과를 memorizing 하도록 래핑한다.
  • 즉 React는 컴포넌트를 렌더링하지 않고 마지막으로 렌더링된 결과를 재사용한다.

참고 코드)

import React, { useEffect, useState } from 'react';
const Textview = React.memo(({ text }) => {
  useEffect(() => {
    console.log(`Update :: Text : ${text}`);
  });
  return <div>{text}</div>;
});

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 value={text} onChange={(e) => setText(e.target.value)} />
      </div>
    </div>
  );
};

export default OptimizeTest;

 

# Q & A

  • CounterA에서는 A Button을 눌러도 값 자체가 바뀌지 않았으므로 React.memo에 의해 리렌더가 되지 않았는데
  • CounterB에서는 B Button을 눌렀을 때 값이 바뀌지 않는데도 리렌더가 되었다.

  • 자바스크립트에서는 객체를 비교할 때 객체의 주소를 비교하는 얕은 비교를 한다
  • 객체를 깊이 비교하려면 areEqual 함수를 새로 만들어 활용한다

  • 객체의 프로퍼티를 비교하여 같으면 true, 다르면 false를 리턴하는 함수 areEqual을 만들고 React.memo함수의 첫 번째 인자에 재사용 할 컴포넌트, 두 번째 인자에 areEqual 비교함수를 넣어 areEqual이 true면 컴포넌트가 리렌더 되지 않고 false면 리렌더 되도록 한다.