DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Rushab jain
Rushab jain

Posted on

useTransition : The new react 18 hook you probably missed

useTransition

This hook is one of the concurrent APIs released in React 18 that improves your application's overall quality and performance while also making them more user-friendly and responsive.

The useTransition hook is specifically designed to speed up applications and make them feel responsive to users, even when a lot is going on.

What's a transition?

A transition is a change between two states. For example, if you have a button that changes from red to green, that's a transition.

What is useTransition?

Returns a stateful value for the pending state of the transition, and a function to start it.

isPending indicates when a transition is active to show a pending state.

startTransition lets you mark updates in the provided callback as transitions.
-React Docs

i.e

const [isPending, startTransition] = useTransition()
Enter fullscreen mode Exit fullscreen mode

useTransition() returns an array of 2 items:

isPending - It's a boolean value.
The isPending variable simply returns true while the code inside the startTransition hook is running.

startTransition(callback): It is a function that initiates the transition. It accepts a callback function as an argument. When the transition begins, the callback function is executed.

when to use useTransition?

eg: let's take a contrived example we have a very large list of items and an input box we have to search and render the results.

function App() {
  const [input, setInput] = useState('')
  const [list, setList] = useState([])

  const [isPending, startTransition] = useTransition()

  function onChangeHandler(event) {
    setInput(event.target.value)
    const listData = []
    for (let i = 0; i < 5000; i++) {
      listData.push(event.target.value)
    }
    startTransition(() => setList(listData))
  }

  return (
    <div id='app'>
      <input type='text' value={input} onChange={onChangeHandler} />
      <ul>
        {isPending ? (
          <li> Loading.... </li>
        ) : (
          list.map((item, index) => <li key={index}>{item}</li>)
        )}
      </ul>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

when having two states input and list input state is responsible for maintaining the input value and the list state is responsible for maintaining the list of items. essentially the input string is rendered 5000 times in the list.

Because React recognizes that both state updates occur at the same time, it will batch them together and complete both state updates before rendering the component again. This is quite efficient because it only renders the component once after all state changes, rather than twice (once after each state change).

This works fine in most circumstances, though this can cause performance issues in some cases.

Because our list is so large, looping through it and rendering it all on the screen would take a long time and will be very slow to process. This is a problem since the list state update happens at the same time as the input state update, thus the component will not be rendered with the new state values for either state until both have completed processing, which means the input field will feel sluggish. Below is an example of this.

Edit lagging input field react eg

slow sloth

useTransition in action

useTransition()Β can be used toΒ tell ReactΒ that certain state updates have aΒ lower priorityΒ (i.e., all other state updates have a higher priority). these state updates will be performed in parallel with other state updates, but the rendering of the component will not be delayed.

In our code below, we're wrapping setList in our startTransition method, which tells React that our setList state update is low priority. This indicates that the component should rerender as soon as all of our normal state updates are completed, even if this slow state update is not completed. Therefore, if a user interacts with your application, such as by clicking a button or entering data, those interactions will take priority over the code in the startTransition method. This ensures that even if you have extremely slow code executing, your user will be able to interact with the application.

function App() {
  const [input, setInput] = useState('')
  const [list, setList] = useState([])

  const [isPending, startTransition] = useTransition()

  function onChangeHandler(event) {
    setInput(event.target.value)
    const listData = []
    for (let i = 0; i < 5000; i++) {
      listData.push(event.target.value)
    }
    startTransition(() => setList(listData))
  }

  return (
    <div id='app'>
      <input type='text' value={input} onChange={onChangeHandler} />
      <ul>
        {isPending ? (
          <li> Loading.... </li>
        ) : (
          list.map((item, index) => <li key={index}>{item}</li>)
        )}
      </ul>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Edit lagging input field react fixed by useTransition

WOW !!

One thing to keep in mind with this use transition hook is that it should only be used when necessary. Because using the Used Transition forces your app to render more than usual. If we hadn't used useTransition, our input would have been updated, and our application would have been rendered to the page once because it rendered both the input and the list at the same time. When we executed our transition in this manner, our application did two separate renders.

If you wrap everything in its separate start transitions right now, your application will be rendering a lot. When, in reality, if there are minor changes that can all happen at once, it is far better to let them all happen at once. Use useTransition only when you're specifically running into performance issues where you have code that is slowing down or has the potential to slow down your application to reduce the number of times your application needs to rerender.

TL;DR -

import { useTransition } from 'react'

function App() {
  const [isPending, startTransition] = useTransition()

  function handleClick() {
    // do something important
    startTransition(() => {
      // Do something slow, expensive, and takes time...
    })
  }

  return (
    <button onClick={handleClick} disabled={isPending}>
      {isPending ? 'Loading...' : 'Click me'}
    </button>
  )
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

All DEV content is created by the community!

Hey, if you're landing here for the first time, you should know that this website is a global community of folks who blog about their experiences to help folks like you out.

Sign up now if you're curious. It's free!