처음에 계산된 결과값(calculate함수 실행해서 나온 결과값)을 메모리에 저장.
즉 , 컴포넌트가 반복적으로 렌더링되어도, calculate함수를 다시호출하지않고, 이전에 이미 계산된 결과값을 메모리에서 꺼내와서 재사용
useMemo는 계산 비용이 큰 함수의 반환 값을 메모이제이션하여 리렌더링 시 재계산을 방지하는 데 사용
콜백함수
- 우리가 메모이제이션 해줄 값을 return 하는 함수
이 콜백함수가 리턴하는 값= useMemo가 리턴하는 값=value
의존성 배열안의 값이 업데이트될때만 콜백함수를 다시 호출
->메모이제이션된 값 업데이트->다시 메모이제이션
사진 출처:별코딩 유튜브
import React, { useState } from 'react'
import styled from 'styled-components'
const hardCalcul = number => {
console.log('어려운 계산')
for (let i = 0; i < 999999999; i++) {}
return number + 10000
}
const easyCalcul = number => {
console.log('짱쉬운 계산')
return number + 1
}
export default function Home() {
const [hardNum, setHardNum] = useState(1)
const [easyNum, setEasyNum] = useState(1)
const hardSum = hardCalcul(hardNum)
const easySum = easyCalcul(easyNum)
return (
<Container>
<Section>
<h1>어려운 계산기</h1>
<Input
type="number"
value={hardNum}
onChange={e => setHardNum(parseInt(e.target.value))}
/>
<span> + 10000 = {hardSum}</span>
</Section>
<Section>
<h1>쉬운 계산기</h1>
<Input
type="number"
value={easyNum}
onChange={e => setEasyNum(parseInt(e.target.value))}
/>
<span> + 1 = {easySum}</span>
</Section>
</Container>
)
}
처음 렌더링되었을때,
어려운계산은 시간이 많이걸리니까, 쉬운 계산만 해야지! 하고 쉬운계산기의 input을 1 증가 시켰는데... 마치 어려운계산을 한것처럼 버벅거림
또한 콘솔창에는 어려운 계산도 출력되었다.
왜그럴까?
쉬운계산기에 숫자를 증가시켜주면
easyNumber state가 바뀐다. state가 바뀐다는 것은, 즉 App컴포넌트가 다시 렌더링이된다.
const hardSum = hardCalcul(hardNum)
const easySum = easyCalcul(easyNum)
그래서 App안에 잇는 hardsum과 easysum 모두 초기화가된다. 즉,hardCalcul도 실행됨.
easyNumber의 state를 변경할때, hardCalculate 함수가 불리지 않게 하고싶다... ==> useMemo를 쓰자
useMemo : 어떤 조건이 만족됐을때만, 해당 변수가 초기화되게한다.
만약 그 조건이 만족되지않았다면, app컴포넌트가 다시 렌더링되더라도, 다시 초기화시켜주는게 아니라 이전에 이미 갖고있던 값을 그대로 사용
= 메모이제이션
의존성배열안의 값이 바뀔때만 콜백함수가 실행댐.
const hardSum = hardCalcul(hardNum)
👇
const hardSum = useMemo(() => {
return hardCalcul(hardNum)
}, [hardNum])
쉬운계산만 할때, 이제 hardCalcul은 실행되지않는^^
import React, { useState, useEffect, useMemo } from 'react'
import styled from 'styled-components'
export default function UseMemoEx() {
const [number, setNumber] = useState(0)
const [isKorea, setIsKorea] = useState(true)
const location = {
country: isKorea ? '한국' : '외국',
}
//만약 const location=isKorea? '한국':'외국'이면, 원시형데이터string니까
//number가 바껴도 useEffect안에 코드실행안댐.
//오브젝트는 참조형데이터이기때문에, 항상 새로운 오브젝트가 할당되는거임.
//=>useEffect안에 코드실행
useEffect(() => {
console.log('유즈이펙트 호출')
...엄청복잡한함수
}, [location])
return (
<Container>
<Section>
<H1>하루에몇끼먹어요?</H1>
<Input
type="number"
value={number}
onChange={e => setNumber(e.target.value)}
/>
</Section>
<hr />
<Section>
<H1>어느 나라에 있어요?</H1>
<p>나라 : {location.country}</p>
<Btn onClick={() => setIsKorea(!isKorea)}>비행기 타자</Btn>
</Section>
</Container>
)
}
하루에몇끼먹어요 밑 INPUT을 조절하면 number state가 바뀐다.
state가 변하니 역시 UseMemoEx이라는 함수가 다시 호출(렌더링)된다.
그러면, location이라는 오브젝트 변수도, 오브젝트가 또 할당이되는데,
오브젝트는 참조형데이터이기때문에, 항상 새로운 오브젝트가 할당되는거임.
그래서 내가 number의 input을 조절해도
useEffect(() => {
console.log('유즈이펙트 호출')
...엄청복잡한함수
}, [location])
이 코드가 실행되어, 불필요한 코드가 실행되는거다.
나는 isKorea의 state가 변할때만 location이 초기화됐으면좋겠다?
=> useMemo
const location = {
country: isKorea ? '한국' : '외국',
}
const location = useMemo(() => {
return { country: isKorea ? '한국' : '외국' }
}, [isKorea])
참고 : 별코딩 유튜브