โ๏ธ memo()๋ก ์ปดํฌ๋ํธ ๋ถํ์ํ ์ฌ๋ ๋๋ง ๋ง๊ธฐ
- memo() ์ฐ๋ ค๋ฉด 'react' ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก๋ถํฐ import ํด์ค๋ฉด ๋๋ค.
import {memo, useState} from 'react' // memo๋ฅผ import
let Child = memo( function(){ // ์ํ๋ ์ปดํฌ๋ํธ ์ ์ ๋ถ๋ถ ๊ฐ์ธ๊ธฐ
console.log('์ฌ๋ ๋๋ง๋จ')
return <div>์์์</div>
})
function Cart(){
let [count, setCount] = useState(0)
return (
<Child />
<button onClick={()=>{ setCount(count+1) }}> + </button>
)
}
- ์ปดํฌ๋ํธ๋ฅผ let ์ปดํฌ๋ํธ๋ช
= function( ){ } ์ด๋ฐ ์์ผ๋ก ๋ง๋ค์ด์ผ ๊ฐ์ ์ ์๋ค.
- ๊ทธ๋ผ ์ด์ Child๋ก ์ ์ก๋๋ props๊ฐ ๋ณํ๊ฑฐ๋ ๊ทธ๋ฐ ๊ฒฝ์ฐ์๋ง ์ฌ๋ ๋๋ง ๋๋ค.
Q) ๊ทธ๋ผ memo๋ ๋ง ์จ๋ ๋๋๊ฑด๊ฐ?
- memo๋ก ๊ฐ์ผ ์ปดํฌ๋ํธ๋ ํ๋ ์ฌ๋ ๋๋ง์ ์์ํค๋ ค๊ณ ๊ธฐ์กด props์ ๋ฐ๋ props๋ฅผ ๋น๊ตํ๋ ์ฐ์ฐ์ด ์ถ๊ฐ๋ก ์งํ๋๋ค.
- props๊ฐ ํฌ๊ณ ๋ณต์กํ๋ฉด ์ด๊ฑฐ ์์ฒด๋ก ๋ถ๋ด์ด ๋ ์๋ ์๊ธฐ ๋๋ฌธ์ ๊ผญ ํ์ํ ๊ณณ์๋ง ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค.
โ๏ธ ๋น์ทํ๊ฒ ์๊ธด useMemo
- useEffect์ ๋น์ทํ ์ฉ๋, ์ปดํฌ๋ํธ ๋ก๋์ 1ํ๋ง ์คํํ๊ณ ์ถ์ ์ฝ๋๊ฐ ์์ผ๋ฉด ๊ฑฐ๊ธฐ ๋ด์ผ๋ฉด ๋๋ค.
import {useMemo, useState} from 'react'
function ํจ์(){
return ๋ฐ๋ณต๋ฌธ10์ต๋ฒ๋๋ฆฐ๊ฒฐ๊ณผ
}
function Cart(){
let result = useMemo(()=>{ return ํจ์() }, [])
return (
<Child />
<button onClick={()=>{ setCount(count+1) }}> + </button>
)
}
- ์๋ฅผ ๋ค์ด ๋ฐ๋ณต๋ฌธ์ 10์ต๋ฒ ๋๋ ค์ผํ๋ ๊ฒฝ์ฐ
- ๊ทธ ํจ์๋ฅผ useMemo ์์ ๋ฃ์ด๋๋ฉด ์ปดํฌ๋ํธ ๋ก๋์ 1ํ๋ง ์คํ๋๋ค.
- dependency๋ ๋ฃ์ ์ ์์ด์ ํน์ state, props๊ฐ ๋ณํ ๋๋ง ์คํํ ์๋ ์๋ค.
โ๏ธ ์ผ๊ด๋ batching & useTransition
โ๏ธ ๋ฆฌ์กํธ 18๋ฒ์ ๋ถํฐ ์ถ๊ฐ๋ ๊ธฐ๋ฅ 1: ์ผ๊ด๋ batching
- automatic batching ์ด๋ผ๋ ๊ธฐ๋ฅ์ด ์๋๋ฐ ์ผ์ข
์ ์ธ๋ฐ์๋ ์ฌ๋ ๋๋ง ๋ฐฉ์ง๊ธฐ๋ฅ์ด๊ณ batching์ด๋ผ๊ณ ํ๋ค.
fetch().then(() => {
setCount(1) //์ฌ๋ ๋๋ง๋จ
setName(2) //์ฌ๋ ๋๋ง๋จ
})
- ๊ทผ๋ฐ ๋ฌธ์ ๋ ajax ์์ฒญ, setTimeout ์์ state ๋ณ๊ฒฝ ํจ์๊ฐ ์๋ ๊ฒฝ์ฐ batching์ด ์ผ์ด๋์ง ์๋๋ค.
- ๋ฆฌ์กํธ 17๋ฒ์ ๊น์ง ๊ทธ๋ฐ ์์ผ๋ก ์ผ๊ด์ ์ด์ง ์๊ฒ ๋์ํ๋๋ฐ 18๋ฒ์ ์ดํ๋ถํฐ๋ ์ด๋ ์๋ ์ฌ๋ ๋๋ง์ ๋ง์ง๋ง 1๋ฒ๋ง ๋๋ค.
- batching ๋๋๊ฒ ์ซ๊ณ state ๋ณ๊ฒฝ ํจ์ ์คํ๋ง๋ค ์ฌ๋ ๋๋ง์ํค๊ณ ์ถ์ผ๋ฉด flushSync๋ผ๋ ํจ์ ์ฌ์ฉํ๋ฉด ๋จ.
โ๏ธ ๋ฆฌ์กํธ 18๋ฒ์ ๋ถํฐ ์ถ๊ฐ๋ ๊ธฐ๋ฅ 2 : useTransition ์ถ๊ฐ๋จ
- ๋ ๋๋ง์๊ฐ์ด ๋งค์ฐ ์ค๋๊ฑธ๋ฆฌ๋ ์ปดํฌ๋ํธ๊ฐ ์๋ค ์น๊ณ
- ๋ฒํผ ํด๋ฆญ, ํ์ดํํ ๋๋ง๋ค ๊ทธ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํด์ผํ๋ค๋ฉด ๋ฒํผ ํด๋ฆญ, ํ์ดํ ๋ฐ์์๋๋ ๋๋ ค์ง๋ค.
- ์ด๋ด ๋ ์ฌ์ฉํ๋ ๊ฒ์ด useTransition ๊ธฐ๋ฅ์ด๋ค.
import {useState, useTransition} from 'react'
let a = new Array(10000).fill(0)
function App(){
let [name, setName] = useState('')
let [isPending, startTransition] = useTransition()
return (
<div>
<input onChange={ (e)=>{
startTransition(()=>{
setName(e.target.value)
})
}}/>
{
a.map(()=>{
return <div>{name}</div>
})
}
</div>
)
}
- useTransition() ์ฐ๋ฉด ๊ทธ ์๋ฆฌ์ [๋ณ์, ํจ์]๊ฐ ๋จ๋๋ค.
- ๊ทธ ์ค ์ฐ์ธก์ ์๋ startTransition() ํจ์๋ก state๋ณ๊ฒฝํจ์ ๊ฐ์๊ฑธ ๋ฌถ์ผ๋ฉด ๊ทธ๊ฑธ ๋ค๋ฅธ ์ฝ๋๋ค๋ณด๋ค ๋์ค์ ์ฒ๋ฆฌํด์ค๋ค.(ํน์ ์ฝ๋์ ์คํ์์ ์ ๋ค๋ก ์ฎ๊ฒจ์ฃผ๋ ๊ฒ)
- ๊ทธ๋์ <input> ํ์ดํ ๊ฐ์ด ์ฆ๊ฐ ๋ฐ์ํด์ผํ๋ ๊ฑธ ์ฐ์ ์ ์ผ๋ก ์ฒ๋ฆฌํด์ค ์ ์๋ค.
- ๋ฌผ๋ก ๊ทผ๋ณธ์ ์ธ ์ฑ๋ฅ๊ฐ์ ์ ์๋๊ธฐ ๋๋ฌธ์ html์ด ๋ง์ผ๋ฉด ์ฌ๋ฌ ํ์ด์ง๋ก ์ชผ๊ฐ๋ ๊ฒ์ด ์ข๋ค.
๐โ๏ธ isPending์ ์ด๋๋ค ์ฐ๋๋ฉด
- startTransition() ์ผ๋ก ๊ฐ์ผ ์ฝ๋๊ฐ ์ฒ๋ฆฌ์ค์ผ ๋ true๋ก ๋ณํ๋ ๋ณ์
{
isPending ? "๋ก๋ฉ์ค๊ธฐ๋ค๋ฆฌ์
" :
a.map(()=>{
return <div>{name}</div>
})
}
โ๏ธ useDeferredValue
- startTransition() ์ด๊ฑฐ๋ ์ฉ๋๊ฐ ๋๊ฐ์๋ฐ state ์๋๋ฉด ๋ณ์ ํ๋๋ฅผ ์ง์ด๋ฃ์ ์ ์๊ฒ ๋์ด ์๋ค.
- ๊ทธ๋์ ๊ทธ ๋ณ์์ ๋ณ๋์ฌํญ์ด ์๊ธฐ๋ฉด ๊ทธ๊ฑธ ๋ฆ๊ฒ ์ฒ๋ฆฌํด์ค๋ค.
import {useState, useTransition, useDeferredValue} from 'react'
let a = new Array(10000).fill(0)
function App(){
let [name, setName] = useState('')
let state1 = useDeferredValue(name)
return (
<div>
<input onChange={ (e)=>{
setName(e.target.value)
}}/>
{
a.map(()=>{
return <div>{state1}</div>
})
}
</div>
)
}
- useDeferredValue ์์ state๋ฅผ ์ง์ด๋ฃ์ผ๋ฉด ๊ทธ state๊ฐ ๋ณ๋์ฌํญ์ด ์๊ฒผ์ ๋ ๋์ค์ ์ฒ๋ฆฌํด์ฃผ๊ณ
- ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ let state์ ์ ์ฅํด์ค๋ค.
๋ณธ ํฌ์คํ ์ << React ๋ฆฌ์กํธ ๊ธฐ์ด๋ถํฐ ์ผํ๋ชฐ ํ๋ก์ ํธ๊น์ง! >> ๊ฐ์๋ฅผ ์ฐธ๊ณ ํฉ๋๋ค.