react-async-ui
v0.2.2
Published
Asynchronous React hooks to manage modal UI state
Downloads
53
Readme
react-async-ui
This package provides state management primitives to build modal user interactions that you can await
, resolve
and reject
using a familiar, Promise
-based API.
Design goals
- Provide lightweight building blocks to express modal UI behavior as
async
/await
workflows - Provide a headless hooks-based API that keeps you flexible in your choice of UI component library and styling solution
- Provide first-class TypeScript support and documentation
Installation
npm install react-async-ui
API
The react-async-ui package exports the useAsyncModalState
hook to manage the lifecycle of a modal UI element that can be shown, await
'ed, and can optionally accept parameters and return a result to the caller.
const [state, showModal] = useAsyncModalState<TValue, TResult>()
Similar to React's setState
hook, it returns an array with exactly two elements:
state
: Represents the current interaction state. This object has the following properties:| Name | Description | | ---- | ----------- | |
isOpen
|true
if the modal is open,false
otherwise | |props
| (Only available whenisOpen
istrue
) | |props.value
| The (optional) parameter passed toshowModal()
| |props.resolve()
| Completes the modal interaction. Takes an optionalresult
parameter that will be returned fromshowModal()
. | |props.reject()
| Fails the modal interaction with an exception. Takes an optionalreason
parameter that will be thrown fromshowModal()
. |showModal()
: A callback to open the modal and optionally pass along a parameter value. It returns aPromise
object, so you canawait
it to obtain the result of the modal interaction when the modal component callsstate.props.{resolve|reject}
:const result = await showModal(42)
Example
Let's build a simple greeter dialog that takes a single string argument (i.e., the name of the person to greet) and can be dismissed through "OK" and "Cancel" buttons:
import { useAsyncModalState } from 'react-async-ui'
function App() {
// Declare state for a modal interaction that takes a string
// argument and completes with either 'ok' or 'cancel'
const [state, showModal] = useAsyncModalState<string, 'ok' | 'cancel'>()
const sayHello = async () => {
const result = await showModal('world')
if (result === 'ok') {
// TODO: Handle "ok" result
}
}
return (
<>
<button onClick={sayHello}>
Say hello!
</button>
{/* Only render dialog when state says it's open */}
{state.isOpen && <GreeterDialog {...state.props} />}
</>
)
}
The corresponding dialog component then uses state.props
to access the passed value and return a result through showModal
:
import { AsyncModalProps } from 'react-async-ui'
function GreeterDialog({ value, resolve }: AsyncModalProps<string, 'ok' | 'cancel'>) {
return (
<dialog open>
<p>Hello, {value}!</p>
<button onClick={() => resolve('ok')}> OK </button>
<button onClick={() => resolve('cancel')}> Cancel </button>
</dialog>
)
}