<h1 align="center">
  <br/>
  <br/>
  👟
  <br />
  use-transition-state
  <br />
  <br />
  <br />
  <br />
</h1>

<p align="center">useTransition + useState = useTransitionState</p>

<div align="center">

[![npm version](https://img.shields.io/npm/v/use-transition-state?style=flat-square)](https://www.npmjs.com/package/use-transition-state)
[![npm downloads](https://img.shields.io/npm/dt/use-transition-state?style=flat-square)](https://www.npmtrends.com/use-transition-state)
[![gzip size](https://badgen.net/bundlephobia/minzip/use-transition-state?label=gzip%20size&style=flat-square)](https://bundlephobia.com/result?p=use-transition-state)
[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)

</div>

## Announcement

This hook builds on top of [React.useTransition](https://github.com/reactwg/react-18/discussions/41) to reduce the verbose of using in conjunction with [React.useState](https://reactjs.org/docs/hooks-reference.html#usestate). However, the `React.useTransition` comes from [React v18](https://github.com/reactwg/react-18) that isn't official released yet. Which means **the hook is in experimental stage** and API might be changed in the near future.

## Requirement

To use `use-transition-state`, you must use `react@18.0.0` or greater.

## Installation

This package is distributed via [npm](https://www.npmjs.com/package/use-transition-state).

```sh
$ yarn add use-transition-state
# or
$ npm install --save use-transition-state
```

## Basic Usage

Here's the basic concept of how it rocks.

Before:

```js
import { useState, useTransition } from "react";

const App = () => {
  const [searchQuery, setSearchQuery] = useState(null);
  const [isPending, startTransition] = useTransition({ timeoutMs: 500 });

  const handleInputChange = (e) => {
    startTransition(() => {
      setSearchQuery(getParsedData(e.target.value));
    });
  };

  return (
    <div>
      <input onChange={handleInputChange} />
      {isPending && "⏳ Loading..."}
      <div>{searchQuery || "🔍 Start search"}</div>
    </div>
  );
};
```

After:

```js
import useTransitionState from "use-transition-state";

const App = () => {
  const [searchQuery, setSearchQuery, { isPending }] = useTransitionState(
    null,
    { timeoutMs: 500 }
  );

  const handleInputChange = (e) => {
    setSearchQuery(getParsedData(e.target.value));
  };

  return (
    <div>
      <input onChange={handleInputChange} />
      {isPending && "⏳ Loading..."}
      <div>{searchQuery || "🔍 Start search"}</div>
    </div>
  );
};
```

## API

The DX of the hook is similar with [React.useState](https://reactjs.org/docs/hooks-reference.html#usestate). You can also access all the APIs of [React.useTransition](https://github.com/reactwg/react-18/discussions/41) when needed.

```js
const [
  state,
  setState, // A React dispatch function with `startTransition`
  {
    isPending,
    startTransition,
    setState, // A React dispatch function without `startTransition`
  },
] = useTransitionState(initialState, { timeoutMs });
```

## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tr>
    <td align="center"><a href="http://wellyshen.com"><img src="https://avatars.githubusercontent.com/u/21308003?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Welly</b></sub></a><br /><a href="#ideas-wellyshen" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/wellyshen/use-transition-state/commits?author=wellyshen" title="Code">💻</a> <a href="https://github.com/wellyshen/use-transition-state/commits?author=wellyshen" title="Documentation">📖</a> <a href="#infra-wellyshen" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-wellyshen" title="Maintenance">🚧</a></td>
  </tr>
</table>

<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
