느린 컴포넌트 성능 향상 useTransition, useDeferredValue

2022. 12. 11. 17:45Study/React

react 18 버전에서 새롭게 추가된 hook이 있다.

 

useTransition

useTransition을 사용하면 동작이 느린 컴포넌트들을 혁신적으로 빠르게 동작시킬 수가 있다.

// App.js

import { useState } from "react";

function App(){
        let [name, setName] = useState('');
        let arr = new Array(10000).fill(0);	// 0이 10000개 담긴 arr
    
    return (
        <div className="App">
            <input onChange={(e)=>{ setName(e.target.value) }} />
            {
                arr.map(()=>{
                	return <div>{name}</div>
                })
            }
        </div>
    )
}

input에 유저가 글을 입력하게 되면 그 값을 name 이라는 state에 저장한 후 arr의 갯수(10000개)만큼 뿌려주는 코드다.

유저가 타이핑을 입력할때마다 10000개의 div박스를 생성하기 때문에 매우 느리다.

 

 

성능저하의 원인이 되는 부분을 startTransition으로 감싼다.

// App.js

import { useState, useTransition } from "react";

let arr = new Array(10000).fill(0);	// 0이 10000개 담긴 arr

function App(){
        let [name, setName] = useState('');
        let [isPending, startTransition] = useTransition()
    
    return (
        <div className="App">
            <input onChange={(e)=>{
            	startTransition(()=>{
                	setName(e.target.value)
                })
            }} />
            {
            	isPending
                ? '로딩중...'
                : arr.map(()=>{
                	return <div>{name}</div>
                })
            }
        </div>
    )
}

브라우저는 한번에 한가지 작업밖에 못하는데,

위의 같은 경우에는 input에 글자를 보여주기, div * 10000 만들기 2가지 일을 해야 하기때문에 버벅거리게 된다.

그런데 startTransition 함수로 감싸게 되면 startTransition안의 코드를 늦게 실행한다.

 

startTransition으로 실행 시점을 조절함으로써 성능 향상의 효과를 기대할 수 있다.

startTransition === 늦게처리

 

isPending은 startTransition이 처리중일 때 true를 반환한다.

 

 

useDeferredValue

useDeferredValue를 사용해도 느린 컴포넌트의 성능을 향상시킬 수있다.

useDeferredValue() 함수 안에 넣은 state는 늦게 처리해준다.

// App.js

import { useState, useTransition, useDeferredValue } from "react";

let arr = new Array(10000).fill(0);	// 0이 10000개 담긴 arr

function App(){
        let [name, setName] = useState('');
        let [isPending, startTransition] = useTransition()
        let state = useDeferredValue(name)
    
    return (
        <div className="App">
            <input onChange={(e)=>{
            	startTransition(()=>{
                	setName(e.target.value)
                })
            }} />
            {
            	isPending
                ? '로딩중...'
                : arr.map(()=>{
                	return <div>{state}</div>
                })
            }
        </div>
    )
}