DEV Community

Cover image for A Guide to Asynchronous result of React modal
Polarisiota
Polarisiota

Posted on

A Guide to Asynchronous result of React modal

This guide is about to get an asynchronous result from react modal.

Sometimes, we want to wait until user select a choice showing a modal, then proceed the following codes based on the user's choice.

Image description

Create the modal component

Modal.js

import React from 'react'
import './modal.css'

export default function Modal({isShow, onClose, message}) {
  return isShow && <div className="modal-overlay">
  <div className="modal">
    {message}
    <div className="modal-action">
      <button onClick={()=>onClose(true)}>OK</button>
      <button onClick={()=>onClose(false)}>Cancel</button>
    </div>
  </div>
  </div>
}
Enter fullscreen mode Exit fullscreen mode

Here I created a simple message modal component.
This modal returns a 'true/false' when a user clicks on OK or Cancel buttons.

Create the Modal Context Provider

context.js

import {createContext} from 'react';

export const ModalContext = createContext({
  show: () => {}
})
Enter fullscreen mode Exit fullscreen mode

Image description
ModalProvider.js

import React, {useState, useRef, useCallback, createContext, useEffect} from 'react'
import Modal from './Modal'
import {ModalContext} from './context'


export default function ModalProvider({children}) {
  const [isShow, setIsShow] = useState(false);
  const [message, setMessage] = useState("");
  const promiseRef = useRef();

  const show = useCallback((message) => {
    setIsShow(true);
    setMessage(message);

    return new Promise((resolve, reject) => {
      promiseRef.current = {resolve, reject};
    })
  }, [])  

  return <ModalContext.Provider value={{show}}>
    {children}
    <Modal isShow={isShow} onClose={(response) => {
    setIsShow(false);
    if (promiseRef.current) {
      promiseRef.current.resolve(response)
    }
    promiseRef.current = null
    }} message={message} />
  </ModalContext.Provider>
}
Enter fullscreen mode Exit fullscreen mode

app.js

import {useContext} from "react"
import './App.css'
import {ModalContext} from './modal/context'

export default function App() {
  const modal = useContext(ModalContext);

  const onShowButtonClick = async () => {
    const result = await modal.show("Hello World!");
    alert('result');
  }
  return (
    <main>
      <h1>React Asyncronous Confirm Modal</h1>
      <div>
        <p>Click the button to show a async confirm modal</p>
        <button onClick={onShowButtonClick}>Show</button>
      </div>
    </main>
  )
}
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

This is a simple and useful way I've found to get the user's choice when I have to proceed the following codes related to the user's decision.
Live Code

Top comments (0)