useMemo 와 useCallback

rkdghwnd·2023년 5월 2일
0

useMemo

useMemo는 리액트 렌더링 과정에서 '특정 값이 바뀌었을 때만 연산을 실행하고,
원하는 값이 바뀌지 않았으면 이전에 연산했던 결과를 다시 사용하는 방식'의 훅이다.

  • useMemo의 첫 번째 인자에는 실행시킬 함수(값을 리턴하는 함수)를 넣고, 두번째 인자에는 배열을 넣는다. 두번째 인자의 배열에 상태변수 넣으면 해당하는 상태가 변경될 때마다 첫번째 인자인 함수를 실행한다.
  • 렌더링을 최적화 하는 훅이기 때문에 렌더링에 사용되지 않는 값은(return 문 안에서 사용하지 않는 경우) 적용할 필요가 없다.
  • 함수로 호출한 값을 사용하거나 복잡한 연산을 하여 값을 얻는경우 사용하면 좋으나, 너무 많이 사용하면 메모리에 쌓이는 값이 커지기 때문에 특정 상황에서만 사용하는 것이 좋다
    https://javascript.plainenglish.io/stop-using-usememo-now-e5d07d2bbf70
    https://react.dev/reference/react/useMemo#usage
import React, { useState, useMemo } from 'react';
 
const getAverage = numbers => {
  console.log('평균값 계산 중..');
  if (numbers.length === 0) return 0;
  const sum = numbers.reduce((a, b) => a + b);
  return sum / numbers.length;
};
 
const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState('');
 
  const onChange = e => {
    setNumber(e.target.value);
  };
  const onInsert = () => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber('');
  };
 
  const avg = useMemo(() => getAverage(list), [list]);
 
  return (
    <div>
      <input value={number} onChange={onChange} />
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <div>
        <b>평균값:</b> {avg}
      </div>
    </div>
  );
};
 
export default Average;

위 코드 에서는 avg 값에 useMemo를 사용해 list값이 바뀔때만 연산을 진행하도록 하여 렌더링을 최적화 하였다.

useCallback

useCallback은 함수를 재사용하는 훅으로, 지정한 특정값이 변경될 때만 함수를 업데이트 하고, 그렇지 않을 때는 기존의 함수를 재사용하는 방식으로 함수의 렌더링을 최적화 한다.

  • useCallback의 첫 번째 인자에는 생성하고 싶은 함수를 넣고, 두 번째 인자로는 배열을 넣는다.
    두 번재 인자인 배열의 요소로 상태변수를 넣으면, 해당 상태변수가 업데이트 될 때 마다 첫번째 인자인 함수도 업데이트된다.
import React, { useState, useMemo, useCallback } from 'react';
 
const getAverage = numbers => {
  console.log('평균값 계산 중..');
  if (numbers.length === 0) return 0;
  const sum = numbers.reduce((a, b) => a + b);
  return sum / numbers.length;
};
 
const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState('');
 
  const onChange = useCallback(e => {
    setNumber(e.target.value);
}, []); // 컴포넌트가 처음 렌더링될 때만 함수 생성
const onInsert = useCallback(() => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber('');
  }, [number, list]); // number 혹은 list가 바뀌었을 때만 함수 생성
 
  const avg = useMemo(() => getAverage(list), [list]);
 
  return (
    <div>
      <input value={number} onChange={onChange}  />
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <div>
        <b>평균값:</b> {avg}
      </div>
    </div>
  );
};
 
export default Average;
profile
rkdghwnd's dev story

0개의 댓글