[react] useMemo hook 사용하기

유나니·2020년 10월 20일

react_til

목록 보기
1/2

Intro

useMemo 를 사용하면 함수형 컴포넌트 내부에서 발생하는 연산을 최적화할 수 있다. 리액트는 기본적으로 state의 값이 변할 때 마다 새로 렌더링이 이뤄진다. 특정 state 값이 변할 때에만 렌더링을 새로 하면 효율적이겠지만 기본적으로 state의 값 중 하나라도 변하면 렌더링이 새로 이뤄진다는 의미이다. useMemo특정 값이 변했을 경우에만 연산을 실행하고 그렇지 않으면 캐싱되어 있는 결과를 사용하는 방식으로 최적화를 하기 위한 hook이다.

평균값을 구하는 컴포넌트

average.js

import React, { useState } from "react";

const getAverage = num => {
  console.log('평균값을 계산중입니다.....')
  if (num.length === 0) return 0
  const sum = num.reduce((a,b) => a+b)
  return sum / num.length
}

const Average = () => {
  const [list, setList] = useState([])
  const [num, setNum] = useState('')

  const onChange = e => {
    const { value } = e.target
    if (!isNaN(Number(value))) {
      setNum(value)
    } else {
      alert('숫자만 입력 가능합니다.')
    }
  }
  const onInsert = () => {
    const nextList = [...list, parseInt(num)]
    setList(nextList)
    setNum('')
  }
  return (
    <div>
      <input value={num} onChange={onChange} type="text"/>
      <button onClick={onInsert}>submit</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <div>
        <b>avg</b>: {getAverage(list)}
      </div>
    </div>
  )
}

export default Average
  • 우선 평균을 구할 숫자들을 담은 list 배열과 숫자 num 을 state로 갖는다.

  • 인풋 태그의 value 가 바뀔 때 마다 숫자가 맞으면 num 을 갱신해준다.

  • submit 버튼 클릭 시 list 배열에 갱신된 num 을 넣어준다.

  • {getAverage(list)} 로 평균을 보여준다.

스크린샷 2020-10-21 오전 1 03 40

하지만 이러한 방식은 두 번째 과정에서 num을 갱신해줄 때 마다 getAverage 함수를 재실행하기 때문에 최적의 방법이라 말하기 어렵다. 이를 해결하기 위해 list 가 바뀌기 전 까지는 기존 값을 가지고 있다가 바뀐 후에 새로 계산하는 방식을 useMemo 로 구현할 수 있다.

useMemo로 최적화하기

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

const Average = () => {
  ...
  ...
  const avg = useMemo(() => getAverage(list), [list])
  return (
  	...
    ...
    <b>avg</b>: { avg }
  )
}

첫번째 인자에 콜백함수를, 두번째 인자에 변하기를 원하는 state 값을 설정해 주면 해당 값이 변할 때에만 함수를 재실행해 렌더링을 효율적으로 조정할 수 있다. 이를 통해 list 배열이 바뀔 때에만 getAverage 함수를 호출할 수 있다.

profile
User First, Mobile Friendly

0개의 댓글