- ๐งโ๐ป Software Developer since 2015, Front-End most time
- ๐ป Write code to
satisfy myselfsolve problems
Make everything as simple as possible, but not simpler. - Albert Einstein
๐ Context API and Hooks based Modal Provider for react material-ui framework
License: MIT License
@Quernest maybe we can add wrapper function for showModal function in the useModal hook. This wrapper will track modal ids which were created in some component. And in useModal hook we will use useEffect to find out when component which created some modals is destroyed. And when it is destroyed we can use destroyModal to close modals created by this component?
Because if we do not close modals manually when browser back button it is pressed and some component which created modals is destroyed we can have different issues.
Originally posted by @pavelspichonak in #4 (comment)
Is it a known issue/just a factor of React Contexts that all components using this library rerenders when a new library calls useModal?
it should include:
onExited
prop where it is not needed;Regular Modal component (without Transition) does not have built-in onExited
callback inside which the current version of mui-modal-provider
library destroys modals (clears memory).
So do not forget to destroy modals manually or using the destroyOnClose
option.
showModal(
SimpleModal,
undefined,
{
destroyOnClose: true // <-- automatically removes modals that do not have the onExited flag
}
)
1.12.3 -> 2.0.0
I'm wanting to create a self contained Dialog that has some logic in it as well. When the OK button is pressed, the business logic executes and the modal is closed. Is it possible to call hideModal from within the dialog itself?
const ConfirmationDialog: React.FC<Props> = ({ title, description, ...props }) => {
const { hideModal } = useModal();
const handleClose = () => {
// Do stuff here
...
hideModal(); // What is the modal id?
};
return (
<Dialog {...props}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>{description}</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Ok
</Button>
</DialogActions>
</Dialog>
);
};
Meanwhile somewhere else in my app:
showModal(ConfirmationDialog, {
title: 'Hello World',
description: 'description text',
});
Thanks for a great library!
Perhaps the best answer is to:
This would
const modal = useModal();
if (modal === FallbackModal) {
// disable
} else {
const { showModal } = modal;
// showmaol
}
Originally posted by @michaeltford in #84 (comment)
README.md
disableAutoDestroy: false and destroyOnClose : false are not honored (at least not always).
https://github.com/Quernest/mui-modal-provider/blob/master/src/modal-provider.tsx#L165
The onExited should have an options (options.destroyOnClose || disableAutoDestroy) check before calling destroy?
Hi, I tried setting up a lazy-loaded dialog that optionally renders based on what the user selects.
const LazyLoadedDialog = React.lazy(() => import('./MyDialog');
...
showModal(LazyLoadedDialog);
Unfortunately, this doesn't seem to work since showModal is expecting the dialog to be an immediately available component. Is there a way to adjust the showModal function to show lazy-loaded dialogs to help boost app performance?
(Btw, this is a really awesome npm library! I use it at work to make managing modals super easy)
First of all thanks for the awesome package, it makes opening dialogs a whole lot easier โค๏ธ
I just installed your package and got this error:
'./dist/modal.esm.js' does not exist, did you mean './dist/index.js'?'
Locally I hot fixed the issue by removing the "module"
line from package.json
in your installed package.
- "module": "dist/modal.esm.js",
"main": "dist/index.js",
Looking at the tree of the installfolder
tree node_modules/mui-modal-provider
node_modules/mui-modal-provider
โโโ LICENSE
โโโ README.md
โโโ dist
โย ย โโโ ModalContext.d.ts
โย ย โโโ ModalProvider.d.ts
โย ย โโโ constants.d.ts
โย ย โโโ index.d.ts
โย ย โโโ index.js
โย ย โโโ mui-modal-provider.cjs.development.js
โย ย โโโ mui-modal-provider.cjs.development.js.map
โย ย โโโ mui-modal-provider.cjs.production.min.js
โย ย โโโ mui-modal-provider.cjs.production.min.js.map
โย ย โโโ mui-modal-provider.esm.js
โย ย โโโ mui-modal-provider.esm.js.map
โย ย โโโ reducer.d.ts
โย ย โโโ test-utils
โย ย โย ย โโโ LegacyModal.d.ts
โย ย โย ย โโโ Modal.d.ts
โย ย โย ย โโโ index.d.ts
โย ย โโโ types.d.ts
โย ย โโโ useModal.d.ts
โย ย โโโ utils.d.ts
โโโ package.json
I guess this line should be changed into (tested works)
- "module": "dist/modal.esm.js",
+ "module": "dist/mui-modal-provider.esm.js",
Hi, I'm dealing with a situation where I have a dropdown menu which shows a list of options. When the user clicks on an option, it triggers the modal which displays a message, does some background work, and auto-closes. However, when the user clicks the dropdown option, this hides the dropdown menu and automatically unmounts the dropdown option's component. Unfortunately, this is also causing the modal to disappear (a bit surprisingly) even though the modal is rendered at the root of the DOM tree instead of within the component and thus there should be no impact on modal visibility.
I read #5 posted in 2020 and it looks like this behavior was set up on purpose to handle scenarios where the user clicks the browser back button. In my case, I am not worried about the browser back button since the modal auto-closes. Is it possible for us to add a flag option to the showModal
command so that it will not destroy the modal on component unmount if the flag is set to true
?
(I can not move up the code for showing the modal out of the option component into the dropdown component because that would break the SRP principle. I also have a bunch of options for the user to select to do different things and show various modals, so moving all that code into the dropdown component would cause its code size to grow unreasonably large)
As an aside, thanks again for making this great package - I've used it probably 10 times now in various places in my app.
How can I close dialog on back button pressed? and prevent back action in navigator?
Material UI v4.12.0 and v5 have changed the Dialog API from taking onExited
to instead taking a TransitionProps
object with onExited
in it.
peerDeps is currently:
"peerDependencies": {
"@types/react": "^16.8.6",
"react": "^16.8.0",
"react-dom": "^16.8.0"
},
The react deps should probably be updated to handle React 17+.
Also @types/react
is probably not necessary as a peer dep.
Hi community,
I'm using this library in one of our projects for a long time. Today we have found a bug in our application, because someone has moved the <ModalProvider />
down in the component tree and it wasn't noticed until now, because we have a specific scenario where we use it and it was above the <ModalProvider />
. Then I've started wondering how there weren't some errors, like usually happens when you don't use the Provider, and tries to call useContext
e.g.:
const useSomeContext = () => {
const context = useContext(SomeContext);
if (context === undefined) {
throw new Error('useSomeContext must be used within a SomeContextProvider');
}
return context;
};
Then I took a look at the file node_modules/mui-modal-provider/dist/mui-modal-provider.cjs.development.js
and saw that on line 305 the library is making use of the useContext
there. Couldn't this solution I have proposed above be applied there, just to avoid "hidden bugs" like this one we have gone through? I'd be open to contribute if that's something interesting to be applied.
import { ReactNode } from 'react';
import { DialogProps } from '@material-ui/core/Dialog';
export interface IProps extends DialogProps {}
and I have to update types like this:
import { ReactNode } from 'react';
import { DialogProps } from '@material-ui/core/Dialog';
export interface IProps extends DialogProps {
onClose: () => void;
onExited: () => void;
}
Is it your package typings issue or not?
showModal
method.For example if I use showModal like this:
showModal(Modal, modalPropsObject);
I'd like to be able to pass only that props which Modal component declared in its typings for typescript?
Originally posted by @pavelspichonak in #5 (comment)
Hey, is there a way to disable the closing of an dialog, when clicked outside the dialog?
Unfortunately disableBackdropClick has been removed
We cannot override onClose
because of
mui-modal-provider/src/modal-provider.tsx
Line 187 in b6c8bc1
and it's not possible to keep dialog open when clicking on backdrop
Hi, thanks for this awesome library, however, I have some problem regarding to closing current modal and open another new one. Here is the example
const loginModal = showModal(LoginModal, {
onClose: () => {},
onRedirectForgetPwd: () => {},
onRedirectRegister: () => {
loginModal.hide();
showModal(RegisterModal)
},
});
const registerModal = showModal(RegisterModal, {
onClose: () => {},
onRedirectLogin: () => {
registerModal.hide();
showModal(LoginModal)
},
});
onRedirectxxx
was indicated a callback funnction to trigger modal useState().
How can I archive this working? Any clues?
When using the module federation vite plugin, such an error appears:
It turned out to be solved only by correcting imports. #76
Here https://github.com/Quernest/mui-modal-provider/blob/master/src/ModalProvider.tsx#L87 we call hideModal(id);
, it called when user touched backdrop
I want to prevent auto hide on backdrop click , user cannot close modal anyway!
I upgraded mui-modal-provider from 1.3.2
to latest version
If you run the following code, you can see it works well on version 1.3.2
but we have error on latest version
If you clock on Simple dialog
twice you can see
Cannot read property 'props' of undefined
import React from "react";
import ModalProvider, { useModal } from "mui-modal-provider";
import Dialog from "@material-ui/core/Dialog";
import DialogTitle from "@material-ui/core/DialogTitle";
import Button from "@material-ui/core/Button";
// โ๏ธ create the dialog you want to use
const SimpleDialog = ({ title, ...props }) => (
<Dialog {...props}>
<DialogTitle>{title}</DialogTitle>
</Dialog>
);
const Test = ({ onClick, title = "Simple dialog" }) => {
const { showModal, hideModal } = useModal();
return (
<Button
variant="contained"
onClick={() => {
if (onClick) {
onClick(hideModal);
}
showModal(SimpleDialog, { title });
}}
color="primary"
>
simple dialog
</Button>
);
};
const App = () => {
const title = <Test onClick={(hideModal) => hideModal()} />;
return (
<ModalProvider>
<Test title={title} />
</ModalProvider>
);
};
export default App;
If the component hosting useMount was unmounted for some reason before the onClose is called the ModalProvider will fail with an error. This will of course also bypass most error boundaries due to how high up ModalProvider normally would be.
This is because DESTROY_BY_ROOT_ID runs and then HIDE runs and the state is missing the id in payload.id.
https://codesandbox.io/s/vigorous-benz-ign4q?file=/src/App.js
This can happen in real apps if a modal does async things as part of its confirm button. e.g. A confirm dialog's confirm button makes an API call, then on success emits a snackbar and closes the dialog. If that API call had side effects (react-query, GraphQL libraries) that happens to change the app to a state where the component that happens to be hosting useModal no longer exists.
@Quernest How can I update props?
Is there a way to disable closing when clicking outside the modal?
test coverage must be above 90%
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.