본문 바로가기

React/이론공부

React.memo

React.memo 란

- 리액트에서 제공하는 고차 컴포넌트 (HOC)

- Memoization 기법으로 동작한다.

- 컴포넌트가 props 로 동일한 결과를 렌더링하면, React.memo 를 호출하고 결과를 메모이징 하도록 래핑하여 경우에 따라 성능을 향상시킬 수 있다.

- React.memo 는 props 의 변화에만 영향을 준다.

( 함수 컴포넌트 안에서 구현한 state 나 context 의 변화에는 재렌더링 )

고차 컴포넌트? HOC ?

어떤 컴포넌트를 인자로 받아서 최적화된 새로운 컴포넌트를 반환해주는 함수
- 최적화된 새로운 컴포넌트는 렌더링이 될 때마다 prop check 라는 과정을 거쳐서 자신의 props 의 변화를 파악한다.
( props 가 변화가 있다고 인지하면 렌더링을 하고, 변화가 없으면 마지막으로 렌더링 되었던 결과를 재사용해서 렌더링한다. )

 

React.memo 꼭 필요할 때만!
- 컴포넌트가 같은 props 로 자주 렌더링이 될 때
- 컴포넌트가 렌더링이 될때마다 복잡한 로직을 처리해야할 때

 

React.memo 기본 구문

export default React.memo(Component);
export default memo(Component);

- Memo 를 사용할 컴포넌트를 memo 로 감싸주면 된다.

 

React.memo 예제

 

memo 만 사용한 예제

App.js

function App() {
  const [parentAge, setParentAge] = useState(0);
  const [childAge , setChildAge] = useState(0);

  const incrementParentAge = () => {
    setParentAge(parentAge + 1)
  }

  const incrementChildAge = () => {
    setChildAge(childAge + 1)
  }

  console.log("부모 요소 업데이트")

  return (
    <div>
      <h1>부모</h1>
      <p>age : {parentAge}살</p>
      <button onClick={incrementParentAge}>부모 나이 증가</button>
      <button onClick={incrementChildAge}>자녀 나이 증가</button>
      <Child name={"홍길동"} age={childAge}/>
    </div>
  );
}

- 부모 나이가 업데이트가 된다면 자식 컴포넌트 (Child) 도 같이 렌더링이 된다. 그 문제를 막기 위해서 Child 의 props 가 바뀔 때만 Child 컴포넌트가 렌더링 될 수 있도록 해주었다.

Child.jsx

import React, { memo } from "react";

const Child = ({ name, age }) => {
  console.log("자식 요소 업데이트");
  return (
    <div>
      <h3>자녀</h3>
      <p>name : {name}</p>
      <p>age : {age}살</p>
    </div>
  );
};

export default memo(Child);

 

useMemo 를 같이 사용한 예제

function App() {
  const [parentAge, setParentAge] = useState(0);

  const incrementParentAge = () => {
    setParentAge(parentAge + 1)
  }


  console.log("부모 요소 업데이트")

  const name = useMemo(() => {
    return {
      lastName : "홍",
      firstName : "길동"
    }
  }, [])

  return (
    <div>
      <h1>부모</h1>
      <p>age : {parentAge}살</p>
      <button onClick={incrementParentAge}>부모 나이 증가</button>
      <Child name={name} />
    </div>
  );
}

- useMemo 글에서 보았다 싶이, 객체타입은 계속 메모리 주소가 변경되기 때문에, 메모이제이션이 되지 않아서, useMemo 를 사용해서 값을 메모이제이션 해주어야한다.

- 결론은 객체인 name 을 props 로 받아서 React.memo 를 사용해도, 객체타입이기 때문에 App.js 가 렌더링 될 때마다 name 의 메모리 주소가 변경되어서 새로 생성되기때문에 useMemo 를 사용해서 메모이제이션 시켜줘야한다.

 

useCallback 을 같이 사용한 예제

App.js

function App() {
  const [parentAge, setParentAge] = useState(0);

  const incrementParentAge = () => {
    setParentAge(parentAge + 1)
  }

  console.log("부모 요소 업데이트")

  const tellMe = useCallback(() => {
    console.log("길동아 사랑해")
  }, [])

  return (
    <div>
      <h1>부모</h1>
      <p>age : {parentAge}살</p>
      <button onClick={incrementParentAge}>부모 나이 증가</button>
      <Child name={"홍길동"} tellMe={tellMe}/>
    </div>
  );
}

- tellMe 함수를 useCallback 으로 묶어주지 않는다면, App.js 가 렌더링될 때마다 tellMe함수가 재 생성되기 때문에 props 가 바뀌었다고 인지해 자식 요소 (Child) 컴포넌트까지 렌더링이 되버린다.

- 결론은 tellMe 의 함수를 useCallback 을 사용해서 메모이제이션을 해줘서 props가 바뀌지 않았다는 걸 인지하게 해주어야한다.

 

Child.jsx

import React, { memo } from "react";

const Child = ({ name, tellMe }) => {
  console.log("자식 요소 업데이트");
  return (
    <div>
      <h3>자녀</h3>
      <p>이름 : {name}</p>
      <button onClick={tellMe}>엄마 나 사랑해?</button>
    </div>
  );
};

export default memo(Child);

'React > 이론공부' 카테고리의 다른 글

React의 가상돔 (Virtual DOM)  (0) 2023.01.25
React.Fragment  (0) 2023.01.25
[React Hooks] useReducer  (0) 2023.01.25
[React Hooks] useCallback  (0) 2023.01.25
[React Hooks] useMemo  (0) 2023.01.24