react-async-ui
v0.2.3
Published
Asynchronous React hooks to manage modal UI state
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/awaitworkflows - 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-uiAPI
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|trueif the modal is open,falseotherwise | |props| (Only available whenisOpenistrue) | |props.value| The (optional) parameter passed toshowModal()| |props.resolve()| Completes the modal interaction. Takes an optionalresultparameter that will be returned fromshowModal(). | |props.reject()| Fails the modal interaction with an exception. Takes an optionalreasonparameter that will be thrown fromshowModal(). |showModal(): A callback to open the modal and optionally pass along a parameter value. It returns aPromiseobject, so you canawaitit 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>
)
}