useTransition : The new react 18 hook you probably missed
Tags: react, webdev, performance, javascript
Published: 2022-11-21 08:37:13

## 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](https://reactjs.org/docs/hooks-reference.html#usetransition)

_i.e_ 

```js
const [isPending, startTransition] = useTransition()
```

`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.

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

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.
{% codesandbox 026rpe %}

[![Edit lagging input field react eg](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/lagging-input-field-react-eg-026rpe?fontsize=14&hidenavigation=1&theme=dark)


![slow sloth](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/szs99zmet0mv91hzk0pz.gif)
## 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.

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

{% codesandbox op9dft %}

[![Edit lagging input field react fixed by useTransition](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/lagging-input-field-react-fixed-by-usetransition-op9dft?fontsize=14&hidenavigation=1&module=%2Fsrc%2FApp.js&theme=dark)

![WOW !!](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zj6yu0woi9923ajxoop.gif)

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 -

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