본문 바로가기
Study/React

[리액트(React)] 7. 리액트훅(Hook) - 심화편

by _temp 2022. 1. 26.

memo, useMemo, useCallback에 대해서 공부해보자


1. memo

- 컴포넌트 자체를 메모이제이션해서 사용하는 훅

// App.js
import React, { useState } from 'react';
import './App.css'
import Greeting from './components/greeting'
import Title from './components/title';

const App = () => {
  const [num, setNum] = useState(0)
  const onClick = () => {
    const num_plus = num+1
    setNum(num_plus)
  }

  return (
    <div>
      <Title name='2HS'/>
      <Greeting num={num} onClick={onClick}/>
    </div>
    
  );
};

export default App
// components/title.jsx
import React from 'react';

const Title = (props) => {
  return <h1>{props.name}에게 인사 횟수</h1>
 };

export default Title;
// components/greeting.jsx
import React, { memo } from 'react';

const Greeting = memo(
  (props) => {
    return (
      <div>
        <h1>{props.num}</h1>
        <button onClick={props.onClick}> 1증가 </button>
      </div>
    );
}
)

export default Greeting;

영상과 같이 title컴포넌트의 props가 변하지 않았는데도 리렌더링되는 것을 알 수 있다.

이를 방지하기 위해서 title컴포넌트에 memo를 사용하면

// components/title.jsx
import React, { memo } from 'react';

const Title = memo((props) => {
  return(
    <h1>{props.name}에게 인사 횟수</h1>
  );
});

export default Title;

title 컴포넌트의 리렌더링이 되지 않는다.

 

2. useCallback & useMemo

- useCallback : 콜백함수를 메모이제이션해서 기억한다.

다음은 클릭시 값을 1 증가시키는 두 가지 버튼을 메모를 사용해서 구현을 했다. 두 번째는 useCallback을 사용했다.

// App.js
import React, { useCallback, useState } from 'react';
import './App.css'
import Greeting from './components/greeting'

const App = () => {
  const [num, setNum] = useState(0)
  const [other, setOther] = useState(0)
  
  const onClick = () => {
    const num_plus = num+1
    setNum(num_plus)
  }

  const onOtherClick = useCallback(() => {
    const num_plus = other+1
    setOther(num_plus)
  }, [other])

  return (
    <div>
      <Greeting num={num} onClick={onClick}/>
      <Greeting num={other} onClick={onOtherClick}/>
    </div>
    
  );
};

export default App
// components/greeting.jsx
import React, { memo } from 'react';

const Greeting = memo(
  (props) => {
    return (
      <div>
        <h1>{props.num}</h1>
        <button onClick={props.onClick}> 1증가 </button>
      </div>
    );
}
)

export default Greeting;

메모를 사용하였다 하더라도 콜백함수가 props로 전달이 되면 App함수가 실행되면서 해당 콜백함수가 재정의가 된다.

당연히 props가 변한 것으로 인식을 하여 내용은 같지만 다른 객체를 props에 전달한다. 그래서 리렌더링이 되는 것이다.

아래는 이를 방지 한 두 번째 버튼에 useCallback을 사용한 결과이다

콜백함수를 메모이제이션하여 사용해서 props가 바뀐거라고 생각을 하지 않는다

 

- useMemo : 콜백함수를 실행한 return값을 반환한다

useCallback과 비슷하지만 useCallback은 콜백함수 자체를 return하는 반면

useMemo는 함수를 실행한 결과를 return해서 값으로 기억한다.

// App.js
import React, { useCallback, useMemo, useState } from 'react';
import './App.css'
import Greeting from './components/greeting'

const App = () => {
  const [num, setNum] = useState(0)
  const [other, setOther] = useState(0)

  const onClick = () => {
    const num_plus = num+1
    setNum(num_plus)
  }

  const onOtherClick = useCallback(() => {
    const num_plus = other+1
    setOther(num_plus)
  }, [other])

  const sumValue = useMemo(()=> sum(num,other), [num,other])

  function sum(x,y) {
    return x+y
  }

  return (
    <div>
      <Greeting num={num} onClick={onClick}/>
      <Greeting num={other} onClick={onOtherClick}/>
      <h1>합 : {sumValue}</h1>
    </div>
    
  );
};

export default App