Skip to content

Commit b016ec4

Browse files
authored
chore: use hook with modal manager (#453)
1 parent 9a06a62 commit b016ec4

File tree

3 files changed

+38
-29
lines changed

3 files changed

+38
-29
lines changed

react-responsive-modal/src/index.tsx

+11-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import ReactDom from 'react-dom';
33
import cx from 'classnames';
44
import CloseIcon from './CloseIcon';
55
import { FocusTrap } from './FocusTrap';
6-
import modalManager from './modalManager';
6+
import { modalManager, useModalManager } from './modalManager';
77
import { isBrowser, blockNoScroll, unblockNoScroll } from './utils';
88

99
const classes = {
@@ -172,8 +172,10 @@ export const Modal = ({
172172
// it will match the server rendered content
173173
const [showPortal, setShowPortal] = useState(false);
174174

175+
// Hook used to manage multiple modals opened at the same time
176+
useModalManager(refModal, open, blockScroll);
177+
175178
const handleOpen = () => {
176-
modalManager.add(refContainer.current!, blockScroll);
177179
if (blockScroll) {
178180
blockNoScroll();
179181
}
@@ -188,8 +190,12 @@ export const Modal = ({
188190
};
189191

190192
const handleClose = () => {
191-
modalManager.remove(refContainer.current!);
192-
if (blockScroll) {
193+
// Restore the scroll only if there is no modal on the screen
194+
// We filter the modals that are not affecting the scroll
195+
if (
196+
blockScroll &&
197+
modalManager.modals().filter((modal) => modal.blockScroll).length === 0
198+
) {
193199
unblockNoScroll();
194200
}
195201
if (
@@ -204,10 +210,7 @@ export const Modal = ({
204210

205211
const handleKeydown = (event: KeyboardEvent) => {
206212
// Only the last modal need to be escaped when pressing the esc key
207-
if (
208-
event.keyCode !== 27 ||
209-
!modalManager.isTopModal(refContainer.current!)
210-
) {
213+
if (event.keyCode !== 27 || !modalManager.isTopModal(refModal)) {
211214
return;
212215
}
213216

+26-14
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
const modals: { element: HTMLDivElement; blockScroll: boolean }[] = [];
1+
import { Ref, useEffect } from 'react';
2+
3+
let modals: { element: Ref<any>; blockScroll: boolean }[] = [];
24

35
/**
46
* Handle the order of the modals.
57
* Inspired by the material-ui implementation.
68
*/
7-
export default {
9+
export const modalManager = {
810
/**
911
* Return the modals array
1012
*/
@@ -13,25 +15,35 @@ export default {
1315
/**
1416
* Register a new modal
1517
*/
16-
add: (newModal: HTMLDivElement, blockScroll: boolean) => {
17-
if (modals.findIndex((modal) => modal.element === newModal) === -1) {
18-
modals.push({ element: newModal, blockScroll });
19-
}
18+
add: (newModal: Ref<any>, blockScroll: boolean) => {
19+
modals.push({ element: newModal, blockScroll });
2020
},
2121

2222
/**
2323
* Remove a modal
2424
*/
25-
remove: (oldModal: HTMLDivElement) => {
26-
const index = modals.findIndex((modal) => modal.element === oldModal);
27-
if (index !== -1) {
28-
modals.splice(index, 1);
29-
}
25+
remove: (oldModal: Ref<any>) => {
26+
modals = modals.filter((modal) => modal.element !== oldModal);
3027
},
3128

3229
/**
33-
* Check if the modal is the first one on the screen
30+
* When multiple modals are rendered will return true if current modal is the last one
3431
*/
35-
isTopModal: (modal: HTMLDivElement) =>
36-
!!modals.length && modals[modals.length - 1]?.element === modal,
32+
isTopModal: (modal: Ref<any>) =>
33+
!!modals.length && modals[modals.length - 1].element === modal,
3734
};
35+
36+
export function useModalManager(
37+
ref: Ref<any>,
38+
open: boolean,
39+
blockScroll: boolean
40+
) {
41+
useEffect(() => {
42+
if (open) {
43+
modalManager.add(ref, blockScroll);
44+
}
45+
return () => {
46+
modalManager.remove(ref);
47+
};
48+
}, [open, ref]);
49+
}

react-responsive-modal/src/utils.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import noScroll from 'no-scroll';
2-
import modalManager from './modalManager';
32

43
export const isBrowser = typeof window !== 'undefined';
54

@@ -8,10 +7,5 @@ export const blockNoScroll = () => {
87
};
98

109
export const unblockNoScroll = () => {
11-
// Restore the scroll only if there is no modal on the screen
12-
// We filter the modals that are not affecting the scroll
13-
const modals = modalManager.modals().filter((modal) => modal.blockScroll);
14-
if (modals.length === 0) {
15-
noScroll.off();
16-
}
10+
noScroll.off();
1711
};

0 commit comments

Comments
 (0)