Render React components as async functions — _await user interaction_ just like fetching data.
npm install promise-renderpromise-renderRender React components as async functions — _await user interaction_ just like fetching data.
promise-render is a tiny utility that lets you render a React component _imperatively_ and wait for its result via a Promise.
Perfect for confirmation dialogs, pickers, wizards, forms, and any UI that needs to “return a value” to your async code.
- Render any React component and get its output via a Promise
- Call UI from thunks, sagas, services, or any async function
- No context, no event bus, no global stores
- Component automatically unmounts after resolve/reject
- TypeScript support included
```
npm install promise-renderor
yarn add promise-render
promiseRender(Component) returns a pair:
``
const [ asyncFunction, AsyncComponent ] = promiseRender(Component)
- AsyncComponent is a React component you render once (e.g. in a modal root).asyncFunction(props?)
- renders that component and returns a Promise.resolve(value)
- Inside the component, two special props are available:
- — resolves the promise & unmounts the componentreject(error)
- — rejects the promise & unmounts the component
This allows you to control UI flow like this:
``
const result = await asyncFunction(props);
`
import { promiseRender } from 'promise-render';
const ConfirmDelete = ({ resolve }) => ( Delete user?
);
const [confirmDelete, ConfirmDeleteAsync] = promiseRender
// Render the async component once in your root:
function App() {
return (
<>
>
);
}
// Now you can await UI from anywhere:
async function onDeleteClick() {
const confirmed = await confirmDelete();
if (!confirmed) return;
await api.deleteUser();
}
`
- ✅ No global event emitters.
- ✅ No prop drilling.
- ✅ Just await your UI.
You can pass any props to the async function.
They will be forwarded to the component automatically.
`
import { promiseRender } from 'promise-render';
const ConfirmAlert = ({ resolve, text }) => ( {text}
);
const [confirm, ConfirmAlertAsync] = promiseRender
// Render
const deleteUser = createAsyncThunk('deleteUser', async () => {
const confirmed = await confirm({
text: "Are you sure you want to delete this user?",
});
if (!confirmed) return;
await api.deleteUser();
});
`
- ✅ Confirmation dialogs
- ✅ Pickers / Select modals
- ✅ Login or consent popups
- ✅ Form dialogs that “return” values
- ✅ Wizards or multi-step flows
- ✅ Any async interaction that should “pause” logic until user acts
If you ever wished JavaScript had await confirmDialog() — now it does.
`
const NamePrompt = ({ resolve }) => {
const [name, setName] = useState("");
return (
setName(e.target.value)} />
);
};
const [promptName, NamePromptAsync] = promiseRender
async function createItem() {
const name = await promptName();
await api.createItem({ name });
}
`
promise-render handles lifecycle automatically:
- Component mounts when the async function is called
- Component unmounts when resolve or reject is triggered
- The same mounted component instance is reused between calls
No global state or manual cleanup required.
This project is licensed under the MIT License - see the LICENSE file for details.
Feel free to extend or modify this README` according to your preferences!