memo
자식 컴포넌트의 재랜더링 막기
<왜 막을까?>
렌더링 시간이 정말 오래걸리는 자식 컴포넌트라면 부모컴포넌트가 재렌더링 될때 지연시간이 발생하게 된다.
그래서 컴포넌트를 memo라는 함수에 담아서 꼭 필요할때 재렌더링하게 해서 지연시간을 단축시키는 것이다.
import {memo} from 'react';
let Child = memo(function(){
return <div>자식컴포넌트</div>
});
⚠️ 왜 memo를 자주 쓰면 좋지 않을까? ⚠️
memo로 감싸놓은 컴포넌트는 항상 재렌더링 되기 전에 기존 props와 신규 props를 비교하는 비교작업을 한다.
만약 props가 길고 복잡하다면 오히려 성능면에서 손해일 수 있다.
꼭 필요한 무거운 컴포넌트에만 사용하는게 좋다.
useMemo
컴포넌트 로드시 1회만 실행하고 싶은 코드가 있다면 useMemo에 담으면 된다. (useEffect와 비슷한 용도)
useEffect 처럼 dependency도 넣을 수 있어서 특정 state, props가 변할 때만 실행할 수도 있다.
<어떨 때 쓰나요?>
반복문을 1000번 돌려야한다고 가정했을 때, 그 함수를 useMemo에 넣어두면 컴포넌트 로드시 1회만 실행되니 효율적으로 동작한다.
import {useMemo, useState} from 'react'
function 함수(){
return 반복문1000번돌린결과
}
function Cart(){
let result = useMemo(()=>{ return 함수() }, [])
// []가 dependency이다.
return (
<Child />
<button onClick={()=>{ setCount(count+1) }}> + </button>
)
}
batching
setCount(1)
setName(2)
setValue(3)
state변경함수를 연달아서 3개 사용하면 재렌더링도 3번 되어야하지만 batching 기능이 생기면서 재렌더링을 마지막에 1회만 처리해준다.
쓸데없는 재렌더링 방지기능이다.
useTransition
동작이 느린 컴포넌트의 성능을 향상시켜준다.
import {useState} from 'react'
// 데이터가 10000개 들어있는 array 자료
let a = new Array(10000).fill(0)
function App(){
let [name, setName] = useState('')
return (
<div>
<input onChange={ (e)=>{ setName(e.target.value) }}/>
{
// map 반복문을 사용해서 유저가 input에 입력할 때마다 10000개의 div를 생성하게 함.
a.map(()=>{
return <div>{name}</div>
})
}
</div>
)
}
이렇게 되면 유저가 input에 무언가를 입력할 때마다 그 입력한 값을 10000개의 div에 넣어주기 때문에 타이핑한 결과가 바로바로 반응이 오지 않는다.
import {useState, useTransition} from 'react'
let a = new Array(10000).fill(0)
function App(){
let [name, setName] = useState('')
// useTransition()은 아래처럼 사용하면 됩니다~
let [isPending, startTransition] = useTransition()
return (
<div>
<input onChange={ (e)=>{
// useTransition 변경함수로 state변경함수를 묶었다.
// 이렇게하면 다른 코드들보다 나중에 처리해준다.
startTransition(()=>{
setName(e.target.value)
})
}}/>
{
a.map(()=>{
return <div>{name}</div>
})
}
</div>
)
}
<동작 원리>
왜 늦게 동작을 했었냐면 브라우저는 한번에 하나의 작업만 할 수 있는 single-threaded이기 때문이다.
그런데 startTransition으로 감싸주면 그 안에 있는 코드들을 약간 늦게 처리해준다. (실행시점을 약간 뒤로 늦춤)
html이 많다면 여러페이지로 나누자!!!
<isPending는 뭐할때 써요?>
useTransition 변경함수로 감싼 코드들이 처리중일 때 true가 되는 변수다.
{isPending ? '로딩중' : <div>로딩완료</div>}
이런식으로 기능개발을 할 수있다.
useDefeerredValue( )
state아니면 변수 하나를 집어넣을 수 있다. 그래서 그 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>
)
}
출처. 코딩애플