function calculate() {
return 10
}
value = calculate()
value = calculate()
value = calculate()
function Component () {
const value = calculate();
return <div> {value} </div>
};
function calculate () {
return 10
};
useMemo 사용시
const value = useMemo(() => {
return calculate();
}, [item]);
const value = useMemo(() => {
return calculate();
}, []);
UseMemoHook.js
import React, { useMemo, useState } from "react";
const hardCalculate = (number) => {
console.log("어려운 계산");
for (let i = 0; i < 99999999; i++) {} //생각하는 시간
return number + 10000;
};
const easyCalculate = (number) => {
console.log("쉬운 계산");
return number + 1;
};
const UseMemoHook = () => {
const [hardNumber, setHardNumber] = useState(1);
const [easyNumber, setEasyNumber] = useState(1);
const hardSum = hardCalculate(hardNumber);
const easySum = easyCalculate(easyNumber);
return (
<div>
<h3>어려운 계산기</h3>
<input
type="number"
value={hardNumber}
onChange={(e) => setHardNumber(parseInt(e.target.value))}
></input>
<span> + 1000 = {hardSum}</span>
<h3>쉬운 계산기</h3>
<input
type="number"
onChange={(e) => setEasyNumber(parseInt(e.target.value))}
></input>
<span> + 1 = {easySum}</span>
</div>
);
};
export default UseMemoHook;
UseMemoHook은 함수형 컴포넌트기 때문에 쉬운 계산기 또는 어려운 계산기의 숫자를 증가시켜주면 easyNumber State 또는 hardNumber State가 바뀌고 UseMemoHook 컴포넌트가 다시 렌더링 됨
그럼 UseMemoHook 안에 정의되어있는 hardSum과 easySum 두개의 변수 모두 다 다시 초기화 됨
hardCalculate 함수와 easyCalculate 함수가 불리게 됨 -> 의미없이 돌아가게 됨 -> 비효율적임
Q. easyNumber State를 변경할 때 hardCalculate 함수가 불리지 않게 하는 방법은 없을까?
A. useMemo를 사용하자!
어떤 조건이 만족 되었을 때만 변수들이 초기화 되도록 할 수 있음
만약 조건이 만족 되지 않았다면 UseMemoHook 컴포넌트가 다시 렌더링 되더라도 다시 초기화를 시켜주는게 아니라 이전에 가지고 있던 값을 그대로 사용하게 해줌(= Memoization)
useMemo 적용한 코드
import React, { useMemo, useState } from "react";
const hardCalculate = (number) => {
console.log("어려운 계산");
for (let i = 0; i < 99999999; i++) {} //생각하는 시간
return number + 10000;
};
const easyCalculate = (number) => {
console.log("쉬운 계산");
return number + 1;
};
const UseMemoHook = () => {
const [hardNumber, setHardNumber] = useState(1);
const [easyNumber, setEasyNumber] = useState(1);
// const hardSum = hardCalculate(hardNumber);
const hardSum = useMemo(() => {
return hardCalculate(hardNumber);
}, [hardNumber]);
// hardNumber가 변경되어야지 hardCalculate가 다시 불려서 hardSum을 초기화 해줌
// 만약 hardNumber가 변경되지 않았다면 이전 값을 재사용함
const easySum = easyCalculate(easyNumber);
return (
<div>
<h3>어려운 계산기</h3>
<input
type="number"
value={hardNumber}
onChange={(e) => setHardNumber(parseInt(e.target.value))}
></input>
<span> + 1000 = {hardSum}</span>
<h3>쉬운 계산기</h3>
<input
type="number"
onChange={(e) => setEasyNumber(parseInt(e.target.value))}
></input>
<span> + 1 = {easySum}</span>
</div>
);
};
export default UseMemoHook;
const hardSum = useMemo(() => {
return hardCalculate(hardNumber);
}, [hardNumber]);
import React, { useState, useEffect } from "react";
function UseMemoHook2() {
const [number, setNumber] = useState(0);
const [isKorea, setIsKorea] = useState(true);
const location = isKorea ? "한국" : "외국";
useEffect(() => {
console.log("useEffect 호출");
}, [location]);
// 처음 렌더링 될 때, location이 바뀌었을 때만 실행됨
return (
<div>
<h2>하루에 몇끼 먹나요?</h2>
<input
type="number"
value={number}
onChange={(e) => setNumber(e.target.value)}
></input>
<br />
<h2>어느 나라에 있나요?</h2>
<p>나라 : {location}</p>
<button onClick={() => setIsKorea(!isKorea)}>비행기 타자~!</button>
{/* isKorea가 false면 true, true면 false로 바뀌줌 */}
</div>
);
}
export default UseMemoHook2;
처음 렌더링 될 때, 의존성 배열 안의 location이 바뀌었을 때만 실행됨
그런데 의존성으로 전달해준 location이 string과 같은 원시타입이 아니라 object라면 다르게 작동함
원시(Primitive) 타입 VS 객체(Object) 타입
String, Number, Boolean, Null, Undefined, Biglnt, Symbol
어떠한 변수에 원시 타입의 값을 할당하면 그 값은 변수라는 상자에 바로 들어감
원시타입을 제외한 모든 것 (Object, Array ....)
어떠한 변수에 객체 타입의 값을 할당하면 객체는 너무 크기 때문에 바로 변수라는 상자에 들어가는 것이 아니라,
메모리상에 공간이 할당 되어 그 공간에 메모리 안에 보관이 됨
그리고 변수 안에는 그 객체가 담긴 메모리의 주소가 할당이 됨
하지만 object가 모양이 같더라도 메모리상의 주소가 다른 object이기 때문에 location이라는 변수는 또 생성된 object의 주소를 참조하게 됨
해결방안 : UseMemoHook2 컴포넌트가 렌더링이 됐을 때 location 변수가 다시 초기화 되는 것을 막아주면 됨
-> isKorea State가 바뀌었을 때만 초기화가 되게 해주기