This article is a part of the series "React bits"
How to create an imperative useConfirmationModal hook
Ever find your self writing code like this?
export function MyComponent() {
const [modalIsOpen, setModalIsOpen] = useState(false);
const [formData, setFormData] = useState<null | FormData>(null);
return <>
<form
onSubmit={(e) => {
e.preventDefault();
setModalIsOpen(true);
setFormData(new FormData(e.currentTarget));
}}
>
<button type="submit">Submit</form>
</form>
</>
<Modal
isOpen={modalIsOpen}
onClose={() => {
setModalIsOpen(false)
}tit}>
<p>Are you sure?</p>
<button onClick={() => {
setModalIsOpen(false);
}}>Cancel</button>
<button onClick={() => {
setModalIsOpen(false);
// Do whatever with the form data
}}>Confirm</button>
</Modal>
</>
}
This is kind of gross right? We end up including a bunch of logic up in our component for displaying a simple confirmation modal, that messies up and distracts from what we're actually trying to do.
This is where a pattern of encapsulating the open/closed state in a hook, and exposing just the needed parts to the calling components.
Our form with confirmation required can now look like this:
export function MyComponent() {
const [confirmationModal, showConfirmation ] = useConfirmationModal({
title: "Are you sure?",
body: "Some kind of custom text here",
cancelButton: "I am the customised cancel button",
confirmButton: "I am the confirm button",
});
return <>
{confirmationModal}
<form
onSubmit={(e) => {
e.preventDefault();
// Calling the `showConfirmation` function will display the modal.
// If the modal is confirmed, then we trigger the callback passed in.
showConfirmation(() => {
const formData = (e.currentTarget);
//do whatever with the formData;
})
}}
>
<button type="submit">Submit</form>
</form>
</>
}
This is nice right?
Here's how we can implement such a hook:
Unauthorized. Is your Github token valid?
☝️ Interactive demo
Click the button to see the modal
Find this helpful? Disagree with this approach? Let me know in the comments!
Questions? Comments? Criticisms? Get in the comments! 👇
Spotted an error? Edit this page with Github