Call RSuite Modals like a boss.
npm install @rsuite/interactions@next --save
- Easy to call out
alert(),confirm(),prompt()styles modals as you already know how. - Await their return values.
- Multiple calls are queued.
Use it like you are using window.alert(), and you can await it.
const buyNewPhone = useCallback(async () => {
await alert("Congrats! You've got a new iPhone!");
console.log('alert closed');
}, []);alert(
message?: React.ReactNode,
modalConfig?: AlertModalProps
): Promise<void>;
interface WrappedModalProps {
modalProps: ModalProps;
}
interface AlertModalProps extends WrappedModalProps {
okButtonText?: string;
onOk?: (() => void) | (() => Promise<any>);
}okButtonText: Customize "OK" button text.onOk: Callback function when "OK" is clicked. IfonOkreturns aPromise, "OK" button shows loading status until the promise finishes.
Use it like you are using window.confirm() but await its return value.
const confirmSmashPhone = useCallback(async () => {
if (await confirm('Are you sure you what to do this?')) {
alert('Rest in pieces.');
}
}, []);confirm(
message?: React.ReactNode,
modalConfig?: ConfirmModalProps
): Promise<boolean>;
interface WrappedModalProps {
modalProps: ModalProps;
}
interface ConfirmModalProps extends WrappedModalProps {
okButtonText?: string;
okButtonDangerous?: boolean;
cancelButtonText?: string;
onOk?: (() => void) | (() => Promise<any>);
onCancel?: (isSubmitLoading?: boolean) => any;
canCancelOnLoading?: boolean;
}okButtonText: Customize "OK" button text.okButtonDangerous: When settrue, "OK" button is red colored.cancelButtonText: Customize "Cancel" button text.onOk: Callback function when "OK" is clicked. IfonOkreturns aPromise, "OK" button shows loading status until the promise finishes.onCancel: Callback function when "Cancel" is clicked. If not provided, "Cancel" is disabled when "OK" is loading.canCancelOnLoading: WhenonCancelis set, you can still use this option to force disable "Cancel" button.
Use it like you are using window.prompt() but await its return value.
const promptForName = useCallback(async () => {
const name = await prompt('What is your name?');
if (name) {
alert(`It\'s ok, ${name}.`);
}
}, []);prompt(
message?: React.ReactNode,
_default?: string,
modalConfig?: PromptModalProps
): Promise<string | null>;
interface WrappedModalProps {
modalProps: ModalProps;
}
interface PromptModalProps extends WrappedModalProps {
okButtonText?: string;
okButtonDangerous?: boolean;
cancelButtonText?: string;
validate?: (inputValue: string) => boolean;
onOk?: ((inputVal?: string) => void) | ((inputVal: string) => Promise<any>);
onCancel?: (isSubmitLoading?: boolean) => any;
canCancelOnLoading?: boolean;
inputProps?: InputProps;
}okButtonText: Customize "OK" button text.okButtonDangerous: When settrue, "OK" button is red colored.cancelButtonText: Customize "Cancel" button text.validate: Validate current input value. Disable OK button if validation fails.onOk: Callback function when "OK" is clicked, receiving a string representing the user input. IfonOkreturns aPromise, "OK" button shows loading status until the promise finishes.onCancel: Callback function when "Cancel" is clicked. If not provided, "Cancel" is disabled when "OK" is loading.canCancelOnLoading: WhenonCancelis set, you can still use this option to force disable "Cancel" button.inputProps: custom input properties, learn more information aboutInputPropsfrom here
If you use @rsuite/interactions to call alert dialogs in your app, you can easily test it with @testing-library/react.
Say you want to show a confirm dialog when user clicks a button that will delete a post:
import { confirm } from '@rsuite/interactions';
function App() {
async function confirmDeletePost(id) {
if (await confirm('Are you sure?')) {
await api.deletePost(id);
}
}
return <button onClick={() => confirmDeletePost(1)}>Delete post 1</button>;
}And you want to test that the dialog is shown when the button is clicked:
import { render, fireEvent, screen } from '@testing-library/react';
it('Should show a confirm dialog', () => {
const { getByRole } = render(<App />);
fireEvent.click(getByRole('button', { name: /delete post/i }));
// Assume you're using Jest with @testing-library/jest-dom
const dialog = screen.getByRole('alertdialog');
expect(dialog).toBeVisible();
// Assert on its a11y description
expect(dialog).toHaveAccessibleDescription('Are you sure?');
// Or if you're using jest-dom < 5.14, you can assert on its textContent
expect(dialog).toHaveTextContent('Are you sure?');
});MIT licensed