본문 바로가기

WEB/HTML CSS JS

[React.js] 10. hook useMemo

반응형

2023.01.31 - [WEB/HTML CSS JS] - [React.js] 9. 아날로그 시계 만들기

 

useMemo는 컴포넌트 내부에서 연산을 할 때 최적화할 수 있는 hook입니다.

앞에서 만들었던 아날로그 시계는 setInterval 함수를 이용해 100ms마다 새 date를 만듭니다.

로그를 통해 값이 변하는 1초마다 렌더링 되는 걸 알 수 있습니다.

그런데 초가 변할 때 시, 분까지 같이 호출됩니다.

이런 문제를 해결하기 위해 React는 값이 변할 때만 최적화하는 useMemo을 제공합니다.

useMemo

Memoization은 컴퓨터 용어로 이전에 계산한 값을 메모리에 저장해 반복 수행을 제거하는 기술입니다.

즉 우리는 sec가 변할 때 min, hour는 기존 계산된 값을 사용하도록 만드는 것이 목표입니다.

useMemo의 파라미터

  • callbackFnc
  • Array

다른 hook과 마찬가지로 사용방법이 간단합니다.

const memoHour = useMemo(() => {
    console.log("hour fnc");
    return hour % 12 * 360 / 12;
}, [hour]);

hour을 Memoization 하면 계산값이 메모리에 저장되고 두 번째 파라미터 배열값에 변화가 없다면 그대로 사용합니다.

주의할 점은 쓸데없는 것들까지 메모리에 저장하면 더 안 좋을 수 있습니다.

이런 식으로 나머지 분, 초까지 작성해 주면 됩니다.

결과를 보면 처음에는 hour, min, sec 모두 호출되지만

그다음부터는 변화가 있을 때만 호출되어 최적화된 모습 입니다.

code

import React, { useEffect, useMemo, useState } from 'react';
import './Timer.css';

const Timer = () => {
    const [hour, setHour] = useState(new Date().getHours());
    const [min, setMin] = useState(new Date().getMinutes());
    const [sec, setSec] = useState(new Date().getSeconds());

    useEffect(() => {
        setInterval(() => {
            const date = new Date();
            setHour(date.getHours());
            setMin(date.getMinutes());
            setSec(date.getSeconds());
        }, 100)
    });

    const memoHour = useMemo(() => {
        console.log("hour fnc");
        return hour % 12 * 360 / 12;
    }, [hour]);
    const memoMin = useMemo(() => {
        console.log("min fnc");
        return min * 360 / 60;
    }, [min]);
    const memoSec = useMemo(() => {
        console.log("sec fnc");
        return sec * 360 / 60;
    }, [sec]);

    return (
        <div className='clock'>
            <div className='hand'>
                <div className='hour' style={{ transform: `rotate(${memoHour}deg)` }}></div>
                <div className='min' style={{ transform: `rotate(${memoMin}deg)` }}></div>
                <div className='sec' style={{ transform: `rotate(${memoSec}deg)` }}></div>
            </div>
        </div>
    );
};

export default Timer;
반응형