Created
November 18, 2019 15:30
-
-
Save ylastapis/789d693960a8260af791746a8b7143a6 to your computer and use it in GitHub Desktop.
Add a Dialog confirmation to any action in any component in React, using Hooks & Context
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { Button } from '../../../components/UI/new/Button'; | |
import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; | |
import { ButtonsContainer } from '../../../components/UI/new/ButtonsContainer'; | |
import { FormattedMessage } from 'react-intl'; | |
export interface ConfirmationOptions { | |
title: string | React.ReactNode; | |
confirmLabel: string | React.ReactNode; | |
description: string | React.ReactNode; | |
} | |
interface ConfirmationDialogProps extends ConfirmationOptions { | |
open: boolean; | |
onSubmit: () => void; | |
onClose: () => void; | |
} | |
export const ConfirmationDialog: React.FC<ConfirmationDialogProps> = ({ | |
open, | |
onSubmit, | |
onClose, | |
title, | |
confirmLabel, | |
description, | |
}) => { | |
return ( | |
<Modal isOpen={open} toggle={onClose}> | |
<ModalHeader toggle={onClose}>{title}</ModalHeader> | |
<ModalBody className="description"> | |
{description} | |
</ModalBody> | |
<ModalFooter> | |
<ButtonsContainer> | |
<Button | |
onClick={onClose} | |
color="secondary" | |
light={true} | |
autoFocus | |
> | |
<FormattedMessage id="global.cancel" /> | |
</Button> | |
<Button | |
color="primary" | |
onClick={onSubmit} | |
> | |
{confirmLabel} | |
</Button> | |
</ButtonsContainer> | |
</ModalFooter> | |
</Modal> | |
); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { ConfirmationDialog, ConfirmationOptions } from './ConfirmationDialog'; | |
const ConfirmationServiceContext = React.createContext<{ | |
openConfirmation: (options: ConfirmationOptions) => Promise<void> | |
}>({ | |
openConfirmation: Promise.reject, | |
}); | |
export const useConfirmation = () => React.useContext(ConfirmationServiceContext); | |
export const ConfirmationServiceProvider: React.FC = ({ | |
children, | |
}) => { | |
const [confirmationState, setConfirmationState] = React.useState<ConfirmationOptions | null>(null); | |
const awaitingPromiseRef = React.useRef<{ | |
resolve: () => void; | |
reject: () => void; | |
}>(); | |
const openConfirmation = (options: ConfirmationOptions) => { | |
setConfirmationState(options); | |
return new Promise<void>((resolve, reject) => { | |
awaitingPromiseRef.current = { resolve, reject }; | |
}); | |
}; | |
const handleClose = () => { | |
setConfirmationState(null); | |
}; | |
const handleSubmit = () => { | |
if (awaitingPromiseRef.current) { | |
awaitingPromiseRef.current.resolve(); | |
} | |
setConfirmationState(null); | |
}; | |
return ( | |
<> | |
<ConfirmationServiceContext.Provider | |
value={{ openConfirmation }} | |
children={children} | |
/> | |
<ConfirmationDialog | |
open={Boolean(confirmationState)} | |
onSubmit={handleSubmit} | |
onClose={handleClose} | |
{...confirmationState!} | |
/> | |
</> | |
); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ConfirmationServiceProvider, useConfirmation } from '../Dialog/ConfirmationService'; | |
export const someFC = () => ( | |
<> | |
<ConfirmationServiceProvider> | |
<ComponentRequiringConfimationPopin /> | |
</ConfirmationServiceProvider> | |
</> | |
); | |
export const ComponentRequiringConfimationPopin = () => { | |
const { openConfirmation } = useConfirmation(); | |
const doYourStuffOnConfirm = useCallback(() => { | |
console.log('confirmed'); | |
}, []) | |
const confirmRefuseSomething = useCallback(() => { | |
openConfirmation({ | |
confirmLabel: "Confirm", | |
title: "Sure bro ?", | |
description: "You really know wwhat youa re doing ?", | |
}) | |
.then(doYourStuffOnConfirm); | |
}, [openConfirmation, doRequest]); | |
return ( | |
<Button | |
onClick={confirmRefuseSomething} | |
> | |
Refusable click | |
</Button> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment