Black Sheep Code
rss_feed

This article is a part of the series "React bits"

How to create an imperative useConfirmationModal hook

Published:

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 onClick ={() => setModalIsOpen(true)} type="submit">Submit</form> 
        </form>
        
        </>
        <Modal isOpen={modalIsOpen} onClose={setModalIsOpen(false)}>

                <button onClick={() => {
                    setFormData(null); 
                    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 messys 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 onClick ={() => setModalIsOpen(true)} type="submit">Submit</form> 
        </form>
        
    </>
}

This is nice right?

Here's how we can implement such a hook:

☝️ Interactive demo

Are you sure?

This is a form

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