본문 바로가기
프론트엔드/React(코딩애플)

React, batching과 useTransition 그리고 useDeferredValue(성능개선)

by Hyeon_E 2023. 3. 28.

일관된 batching

리액트 18버전부터 일관된 batching을 지원

 

automatic batching 이라는 기능이 있는데 state변경함수를 연달아서 여러개 사용하면

재렌더링도 여러개되어야 하지만 리액트는 재렌더링을 마지막에 1회만 처리

이렇게 일종의 쓸데없는 재렌더링 방지기능을 batching이라고 함

 

setName("HE")
setAge(19)
setCount(0)

 

리액트 17버전까지는 ajax요청, setTimeout 등등의 안에 있는 state변경함수가 있는 경우 batching이 일어나지 않았지만

리액트18버전부터는 일관적이게 어디있든간 재렌더링이 마지막 1번만 됨

 

만약 automatic batching을 원하지 않는 경우 flushsync()을 이용

flushsync()는 비동기적인 코드를 강제로 동기적으로 만들고 react에서 리렌더링을 강제하도록 함

 

import { flushSync } from 'react-dom';

flushSync(() => {
  setSomething(123);
});
//다음 코드 줄이 실행될 때까지 react가 DOM을 업데이트

 

flushsync()는 매개변수로 callback함수를 받음

 

useTransition

렌더링 시간이 오래 걸리는 컴포넌트가 있는데 특정반응(타이핑, 클릭 등)에 렌더링해야한다면 특정반응속도가 느려짐

이럴경우 컴포넌트에 Html 갯수를 줄이면 대부분 해결되지만 안된다면 반응속도를 올리는 다른 방법을 생각해야함

이럴때 사용하기 좋은것이 useTransition

 

import {useState, useTransition} from 'react'

let a = new Array(100).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변경함수 같은걸 묶으면 그것을 다른 코드들보다 나중에 처리해줌

그렇기에 특정반응에 반응속도가 훨씬 나아짐

이것을 이용해 타이핑 같이 즉각적으로 반응해야하는것을 우선적으로 처리해줄 수 있음

 

성능개선보다는 특정코드의 실행시점을 뒤로 옮겨주는 것이기 때문에 Html이 많으면 여러페이지로 쪼개는 것이 좋음

 

isPending 이용

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

 

isPending은 startTransition()으로 감싼 코드가 처리중일때 true로 변하는 함수이기 때문에

isPending을 이용하여 유저에게 코드가 처리중일때 알려주기 편함

 

useDeferredValue

startTransition()과 용도가 같음

다만 useDeferredValue는 state 아니면 변수하나를 집어넣을 수 있게 되어있음

매개변수가 변동사항이 생길시 그것을 늦게 처리해줌

 

import {useState, useTransition, useDeferredValue} from 'react'

let a = new Array(100).fill(0)

function App(){
  let [name, setName] = useState('')
  let state = useDeferredValue(name)
  
  return (
    <div>
      <input onChange={ (e)=>{ 
          setName(e.target.value) 
      }}/>

      {
        a.map(()=>{
          return <div>{state}</div>
        })
      }
    </div>
  )
}

 

 

위에 flushsync()의 예시와 같은 결과를 나타냄

useDeferredValue 안에 state를 넣으면 state가 변동사항이 생겼을 때 나중에 처리해주고

처리결과는 변수(여기서는 state)에 저장해줌

'프론트엔드 > React(코딩애플)' 카테고리의 다른 글

React, async  (0) 2023.03.30
React, PWA  (0) 2023.03.30
React, 재렌더링을 막는 memo, useMemo(성능개선)  (0) 2023.03.23
React, React Develop Tools과 lazy import(성능개선)  (0) 2023.03.21
React, react-query  (0) 2023.03.21

댓글