useTransition, useDeferredValue

gotcha!!·2023년 11월 10일
0

React

목록 보기
15/15

리액트 18버전 이후부터는 state 변경함수가 여러 개 있더라도 마지막 state 변경함수 이후에 재렌더링이 된다.
이를 batching 이라고 한다.
근데 만약 batching이 싫다면 flushSync라는 함수를 사용하면 된다.
나중에 참고하자


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>
  )
}

a라는 배열에 0이라는 숫자를 1만개 만들어뒀다.
인풋 박스에 내가 값을 입력할때마다 name이라는 state가 변경이 될 것이고, 1만개의 state가 출력이 된다.
이렇게 하면 현저히 느린 속도를 체감할 수 있다.
유저들이 대거이탈 하겠다.


사용해보자

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 타이핑 같이 즉각 반응해야하는 걸 우선적으로 처리할 수 있고 반응속도가 훨씬 나아질 수 있다.

원리를 알아보자면
내가 입력했던 코드에서 startTransition을 쓰기전에 코드는
유저가 input에 타이핑을 하면 그 글자를 div 1만개 박스 안에 집어넣어줘야하는데,
1만개를 렌더링해주느라 input에서도 지연시간이 발생한다.
그러나
startTransition 으로 감싸주면 startTransition에 감싸진 코드를 늦게 실행해준다.
예를 들어 input 태그에 a 라는 글자를 넣으면
a를 먼저 즉각적으로 보여주고 state 변경함수를 실행하게된다.

근복적으론 성능개선이라기보단 특정 코드 실행시점을 뒤로 옮겨주는 것이다.


isPending은?

isPending은 startTransition()로 감싼 코드가 처리중일 때 true를 반환해주는 변수이다.
그래서 로딩이 좀 걸린다면 로딩중이란 알림을 출력해줄 수 있다.

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) 
        })
      }}/>

      {
        isPending ? '로딩중임' :
        a.map(()=>{
          return <div>{name}</div>
        })
      }
    </div>
  )
}

이렇게 짤 수 있다.


useDeferredValue

useDeferredValue 이거도 startTransition 이랑 비슷하다고 보면된다.
근데 얘는 state 혹은 변수하나를 집어넣을 수 있게 되어있다.
startTransition는 state 변경함수를 집어넣었어야 했는데 말이다!

그래서 useDeferredValue 안에 들어간 변수에 변동사항이 생기면 그걸 늦게 처리해준다.

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) 
      }}/>

      {
        isPending ? '로딩중임' :
        a.map(()=>{
          return <div>{name}</div>
        })
      }
    </div>
  )
}

이렇게 하면 위에 코드랑 기능은 똑같이 개발이 가능하다
useDeferredValue 안에 state를 넣으면 그 state가 변동사항이 생겼을 때 나중에 처리해주고 처리 결과는 let state1에 저장해둔다.

profile
ha lee :)

0개의 댓글

관련 채용 정보