I am working on a React TypeScript webapplication which has lots of different forms. I am currently implementing a feature which displays a warning prompt when for example the user is trying to navigate away from the page if there are unsaved changes in a form i.e., a warning is prompted if there is potential data loss.
Now, prompting users when they try to nagivate away, reloading the page, closing browser tab works fine, using a usePrompt
/ useBlocker
implementation from react-router-dom
which checks for route changes.
However, quite a lot of the forms are placed within react-bootstrap
<Modal>
components. They in general look something like this:
const UpdateDataComponent: React.VFC<UpdateDataComponentProps> = ({ props }) => {
const defaultFormValues = {
//get default form values
};
const [open, setOpen] = useState(false);
const [formValues, setFormValues] = useState(defaultFormValues);
const handleOpen = () => {
setFormValues(defaultFormValues);
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const handleFormSubmit = (e) => {
// submit date
// if successful, closeModal i.e., handleClose()
};
return (
<Fragment>
<Button onClick={handleOpen} />
<Modal onHide={handleClose} show={open}>
<Modal.Header closeButton>
<Modal.Title>
// title
</Modal.Title>
</Modal.Header>
<form onSubmit={handleFormSubmit}>
<Modal.Body>
// data form goes here
</Modal.Body>
<Modal.Footer>
<Button onClick={handleClose}/> // cancel button
<Button/> //submit button
</Modal.Footer>
</form>
</Modal>
</Fragment>
);
};
export default UpdateDataForm;
Given a isDirty
React state (true when there are unsaved changes, false otherwise), I want a component or a hook which prevents closing of the modal and displays a warning prompt if isDirty
is set to true
. This I would like to be done without having to change the code of handleOpen
, handleClose
and handleFormSubmit
(or at least not all of them) as shown above, because I will have to apply these changes in lots of places. The ideal case would to have a custom hook or component with some props which then handles all the logic and the prompting without additional changes.
Any suggestions on how to go about this? Or other ways to look at it?