Some context: I need an async await function or Promise/Resolve to return the button of choice a user selects. The reason I need it this way is because I'm calling a deletePost function from within a specific child Post component and I need a Modal that exists at a parent component level to prompt the user to confirm a Delete or Cancel. I then need that decision to be returned to the child Post component to continue on with the deletion process or cancel it depending on what button the user clicks in the Modal.
The reason it has to be this way is because all the data for the post I want to delete exists at that child Post component level so the entire functionality for deletion of a post needs to be at the Post component level and I'm looking to link that to a Modal at a higher parent level which will allow me to confirm of cancel that deletion process at the click of a button on the modal
import React, { useState } from "react";
const Example = async () => {
const [modalOpen, setModalOpen] = useState(false);
const toggleModal = async () => {
// Opens Modal
setModalOpen(!modalOpen);
let decision = null; // should be "delete" or "cancel" for return
/*
This toggleModal() function will be called from within a child
component's deletePost() function to prompt a user for confirmation
of deletion or cancellation. Once the modal opens up, I believe I
need some kind of async await function HERE to wait on a click
decision from the user and then return that selected value all the
way back to the deletePost() function that was called from within
the child Post component.
*/
return decision;
};
const modalStyle = {
display: modalOpen ? "block" : "hidden",
};
return (
<div>
<button onClick={toggleModal}>Open Modal</button>
<Modal style={modalStyle}>
{/* How to link these buttons to the async await function above */}
<button>Delete</button>
<button>Cancel</button>
</Modal>
{posts.map((post, index) => (
<Post
key={post.id}
post={post}
toggleModal={toggleModal}
/>
))}
</div>
);
};
export default Example;
I am not sure about your exact use case, but if you want to know whether user selected Cancel
or Confirm
, you can do that with attaching separate onClick
event on those two buttons.
import React, { useState } from "react";
const Example = async () => {
const [modalOpen, setModalOpen] = useState(false);
const toggleModal = () => {
// Opens Modal
setModalOpen(!modalOpen);
};
const handleConfirm = () => { //confirm logic }
const handleCancel = () => { //cancel logic }
const modalStyle = {
display: modalOpen ? "block" : "hidden",
};
return (
<div>
<button onClick={toggleModal}>Open Modal</button>
<Modal style={modalStyle}>
<button onClick={handleConfirm}>Confirm</button>
<button onClick={handleCancel}>Cancel</button>
</Modal>
</div>
);
};
export default Example;
This way you keep all the methods separate and don't even need to use async await, i.e. use for user to either click one of those buttons.
Edit: Added this codesandbox based on my understanding of op's comment.
I just published a package to handle your case.
Installation:
npm install use-awaitable-component
Usage:
import React, { useState } from "react";
import useAwaitableComponent from "use-awaitable-component";
const Example = async () => {
const [awaitModalStatus, awaitModalExec, awaitModalResolve, awaitModalReject, awaitModalReset] = useAwaitableComponent();
const modalOpen = awaitModalStatus === 'awaiting' // Show modal while awaiting
const awaitModal = async () => {
try {
const decission = await awaitModalExec();
console.log(decission);
} finally {
awaitModalReset()
}
};
const modalStyle = {
display: modalOpen ? "block" : "hidden",
};
return (
<div>
<button onClick={awaitModal}>Open Modal</button>
<Modal style={modalStyle}>
<button onClick={() => awaitModalResolve('delete')}>Delete</button>
<button onClick={() => awaitModalReset()}>Cancel</button>
</Modal>
{posts.map((post, index) => (
<Post
key={post.id}
post={post}
toggleModal={awaitModal}
/>
))}
</div>
);
};
export default Example;