Refactor modal provider to better use its own state
This commit is contained in:
parent
bdb9af5c4b
commit
fe687cd2f9
@ -8,6 +8,8 @@
|
|||||||
* UI Modal
|
* UI Modal
|
||||||
*
|
*
|
||||||
* @typedef {Object} ModalProps
|
* @typedef {Object} ModalProps
|
||||||
|
* @property {string} [header=null] -
|
||||||
|
* @property {string} [footer=null] -
|
||||||
* @property {string} [backdrop=false] -
|
* @property {string} [backdrop=false] -
|
||||||
* @property {string} [keyboard=false] -
|
* @property {string} [keyboard=false] -
|
||||||
* @property {number} [show=true] -
|
* @property {number} [show=true] -
|
||||||
@ -36,10 +38,12 @@ function createUIModalService() {
|
|||||||
* Show a new UI modal;
|
* Show a new UI modal;
|
||||||
*
|
*
|
||||||
* @param {Modal} component React component
|
* @param {Modal} component React component
|
||||||
* @param {ModalProps} props { backdrop, keyboard, show, closeButton, title, customClassName }
|
* @param {ModalProps} props { header, footer, backdrop, keyboard, show, closeButton, title, customClassName }
|
||||||
*/
|
*/
|
||||||
function show(component, props) {
|
function show(component, props) {
|
||||||
const {
|
const {
|
||||||
|
header = null,
|
||||||
|
footer = null,
|
||||||
backdrop = false,
|
backdrop = false,
|
||||||
keyboard = false,
|
keyboard = false,
|
||||||
show = true,
|
show = true,
|
||||||
@ -48,6 +52,8 @@ function show(component, props) {
|
|||||||
customClassName = null,
|
customClassName = null,
|
||||||
} = props;
|
} = props;
|
||||||
return uiModalServiceImplementation._show(component, {
|
return uiModalServiceImplementation._show(component, {
|
||||||
|
header,
|
||||||
|
footer,
|
||||||
backdrop,
|
backdrop,
|
||||||
keyboard,
|
keyboard,
|
||||||
show,
|
show,
|
||||||
|
|||||||
@ -2,20 +2,22 @@ import React, {
|
|||||||
useState,
|
useState,
|
||||||
createContext,
|
createContext,
|
||||||
useContext,
|
useContext,
|
||||||
useCallback,
|
|
||||||
useEffect,
|
useEffect,
|
||||||
|
useCallback,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
const ModalContext = createContext(null);
|
const ModalContext = createContext(null);
|
||||||
const { Provider, Consumer } = ModalContext;
|
const { Provider } = ModalContext;
|
||||||
|
|
||||||
export const useModal = () => useContext(ModalContext);
|
export const useModal = () => useContext(ModalContext);
|
||||||
|
|
||||||
const ModalProvider = ({ children, modal: Modal, service }) => {
|
const ModalProvider = ({ children, modal: Modal, service }) => {
|
||||||
const DEFAULT_OPTIONS = {
|
const DEFAULT_OPTIONS = {
|
||||||
component: null /* The component instance inside the modal. */,
|
component: null /* The component instance inside the modal. */,
|
||||||
|
header: null /* The content inside the modal header. */,
|
||||||
|
footer: null /* The content inside the modal footer. */,
|
||||||
backdrop: false /* Should the modal render a backdrop overlay. */,
|
backdrop: false /* Should the modal render a backdrop overlay. */,
|
||||||
keyboard: false /* Modal is dismissible via the esc key. */,
|
keyboard: false /* Modal is dismissible via the esc key. */,
|
||||||
show: true /* Make the Modal visible or hidden. */,
|
show: true /* Make the Modal visible or hidden. */,
|
||||||
@ -42,8 +44,10 @@ const ModalProvider = ({ children, modal: Modal, service }) => {
|
|||||||
*
|
*
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
const show = useCallback((component, props = {}) =>
|
const show = useCallback(
|
||||||
setOptions(Object.assign({}, options, props, { component }))
|
(component, props = {}) =>
|
||||||
|
setOptions(Object.assign({}, options, props, { component })),
|
||||||
|
[options]
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,30 +55,30 @@ const ModalProvider = ({ children, modal: Modal, service }) => {
|
|||||||
*
|
*
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
const hide = useCallback(() => setOptions(DEFAULT_OPTIONS));
|
const hide = useCallback(() => setOptions(DEFAULT_OPTIONS), [
|
||||||
|
DEFAULT_OPTIONS,
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Provider value={{ ...options, show, hide }}>
|
<Provider value={{ show, hide }}>
|
||||||
<Consumer>
|
{options.component && (
|
||||||
{props => {
|
<Modal
|
||||||
const { component, footer, header, customClassName } = props;
|
className={classNames(
|
||||||
return component ? (
|
options.customClassName,
|
||||||
<Modal
|
options.component.className
|
||||||
className={classNames(customClassName, component.className)}
|
)}
|
||||||
backdrop={options.backdrop}
|
backdrop={options.backdrop}
|
||||||
keyboard={options.keyboard}
|
keyboard={options.keyboard}
|
||||||
show={options.show}
|
show={options.show}
|
||||||
title={options.title}
|
title={options.title}
|
||||||
closeButton={options.closeButton}
|
closeButton={options.closeButton}
|
||||||
onHide={hide}
|
onHide={hide}
|
||||||
footer={footer}
|
footer={options.footer}
|
||||||
header={header}
|
header={options.header}
|
||||||
>
|
>
|
||||||
{component}
|
{options.component}
|
||||||
</Modal>
|
</Modal>
|
||||||
) : null;
|
)}
|
||||||
}}
|
|
||||||
</Consumer>
|
|
||||||
{children}
|
{children}
|
||||||
</Provider>
|
</Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -38,45 +38,51 @@ const SnackbarProvider = ({ children, service }) => {
|
|||||||
}
|
}
|
||||||
}, [service, hide, show]);
|
}, [service, hide, show]);
|
||||||
|
|
||||||
const show = useCallback(options => {
|
const show = useCallback(
|
||||||
if (!options || (!options.title && !options.message)) {
|
options => {
|
||||||
console.warn(
|
if (!options || (!options.title && !options.message)) {
|
||||||
'Snackbar cannot be rendered without required parameters: title | message'
|
console.warn(
|
||||||
);
|
'Snackbar cannot be rendered without required parameters: title | message'
|
||||||
|
);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newItem = {
|
const newItem = {
|
||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
...options,
|
...options,
|
||||||
id: count,
|
id: count,
|
||||||
visible: true,
|
visible: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
setSnackbarItems(state => [...state, newItem]);
|
setSnackbarItems(state => [...state, newItem]);
|
||||||
setCount(count + 1);
|
setCount(count + 1);
|
||||||
});
|
},
|
||||||
|
[count, DEFAULT_OPTIONS]
|
||||||
|
);
|
||||||
|
|
||||||
const hide = useCallback(id => {
|
const hide = useCallback(
|
||||||
const hideItem = items => {
|
id => {
|
||||||
const newItems = items.map(item => {
|
const hideItem = items => {
|
||||||
if (item.id === id) {
|
const newItems = items.map(item => {
|
||||||
item.visible = false;
|
if (item.id === id) {
|
||||||
}
|
item.visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
|
|
||||||
return newItems;
|
return newItems;
|
||||||
};
|
};
|
||||||
|
|
||||||
setSnackbarItems(state => hideItem(state));
|
setSnackbarItems(state => hideItem(state));
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setSnackbarItems(state => [...state.filter(item => item.id !== id)]);
|
setSnackbarItems(state => [...state.filter(item => item.id !== id)]);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
},
|
||||||
|
[setSnackbarItems]
|
||||||
|
);
|
||||||
|
|
||||||
const hideAll = () => {
|
const hideAll = () => {
|
||||||
// reset count
|
// reset count
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user