리액트 18버전 이후부터 렌더링 성능이 저하되는 컴포넌트에서 쓸 수 있는 기능들이 추가 되었다.
18버전 이후 추가된 기능 1 : 일관된 batching
setCount(1)
setName(2)
setValue(3) //여기서 1번만 재렌더링됨
- state 변경함수를 연달아 사용하면 재렌더링도 원래 3번 되어야 하지만 마지막에 1회만 처리해준다.
- 일종의 불필요한 재렌더링 방지기능이고 batching이라고 한다.
fetch().then(() => {
setCount(1) //재렌더링됨
setName(2) //재렌더링됨
})
- 리액트 17버전까지는 ajax요청, setTimeout안에 state 변경함수가 있는 경우 batching이 일어나지 않았는데,
- 18버전 이후 부터는 어디 있든 간에 재렌더링은 마지막에 1번만 된다.
- batching 되는게 싫고 state 변경마다 재렌더링 시키고 싶으면 flushSync라는 함수를 쓰면 된다.
18버전 이후 추가된 기능 2 : useTransition 추가
렌더링시간이 매우 오래 걸리는 컴포넌트가 있다고 할 때 버튼 클릭, 타이핑 때마다 렌더링이 된다면
버튼 클릭, 타이핑 반응속도도 느려진다. 이런 경우 useTransition을 이용하면 성능 향상을 할 수 있다.
재렌더링 느린 컴포넌트
import {useState} from 'react'
let a = new Array(10000).fill(0)
function App(){
let [name, setName] = useState('')
return (
<div>
<input onChange={ (e)=>{ setName(e.target.value) }}/>
{
a.map(()=>{
return <div>{name}</div>
})
}
</div>
)
}
- 10000개의 0으로 이루어진 array 자료형 변수 a를 만든다.
- input에 onChange 이벤트가 일어날 때마다 name 값이 변경되고 재렌더링이 일어난다.
- <div>{name}</div> 부분이 변수 a의 개수(10000) 만큼 반복되기 때문에 많은 지연시간이 발생한다.
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>
)
}
- 우측에 있는 startTransition() 함수로 state변경함수 같은걸 묶으면 다른 코드들보다 나중에 처리해준다.
- 그래서 <input> 타이핑같이 즉각 반응해야 하는 걸 우선적으로 처리해 줄 수 있다.
- 근본적인 성능개선이라기보단 특정코드의 실행시점을 늦춰주는 기능이다.
{
isPending ? "로딩중" : a.map(() => { return <div>{name}</div> })
}
- 좌측에 있는 isPending은 startTransition()으로 감싼 코드가 처리중일 때 true 값을 가지는 변수다.
- 위 코드는 useTransition으로 감싼 코드의 처리가 완료되면 <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가 변동사항이 생겼을 때 나중에 처리해주고
- 처리 결과는 새로운 변수에 할당해서 그 변수를 이용하면 된다.
'React' 카테고리의 다른 글
[React] 웹에서 flask 서버로 통신해 검색 기능 구현하기 (1) | 2023.12.23 |
---|---|
[React] localhost:3000 -> flask 서버 통신 시 CORS 에러 해결 과정 (1) | 2023.12.23 |
[React] 성능 개선 1. 재렌더링 막는 memo(), useMemo (0) | 2023.12.22 |
[React] Local Storage 사용 방법 (2) | 2023.12.22 |
[React] Redux 라이브러리 설치 및 사용법 (0) | 2023.12.20 |