Created
February 23, 2024 02:09
-
-
Save lighth7015/3acf50429bf80968e21f2998eaeeeb63 to your computer and use it in GitHub Desktop.
Dialog Provider
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, { createContext, useContext, useState, FunctionComponent, useEffect } from 'react'; | |
import { Dialog, Button } from '@mui/material'; | |
type DialogProviderProps = React.PropsWithChildren; | |
type DialogContent = { component: FunctionComponent<any> | null; props: any; }; | |
type ShowDialogFn = ( component: FunctionComponent<any>, props?: any ) => void; | |
type DialogCtx = { showDialog: ShowDialogFn; closeDialog: VoidFunction; open: boolean; content: DialogContent; }; | |
const DialogContext = createContext<DialogCtx | undefined>( undefined ); | |
function invariant ( condition: unknown, message: string ): asserts condition { | |
if ( !condition ) { | |
throw new Error( message ); | |
} | |
} | |
const DialogProvider: React.FC<DialogProviderProps> = ( { children } ) => { | |
const [ isOpen, setIsOpen ] = useState( false ); | |
const [ dialogContent, setDialogContent ] = useState<DialogContent>( { component: null, props: {} } ); | |
const showDialog = ( component: FunctionComponent<any>, props?: any ) => { | |
setIsOpen( true ); | |
setDialogContent( { component, props: props || {} } ); | |
}; | |
const closeDialog = () => { | |
setIsOpen( false ); | |
setDialogContent( { component: null, props: {} } ); | |
}; | |
// Ensure the state is reset on unmount (cleanup for SSR) | |
useEffect( () => { | |
return () => { | |
setIsOpen( false ); | |
setDialogContent( { component: null, props: {} } ); | |
}; | |
}, [] ); | |
// Check if running on the client side | |
const isClient = typeof window !== 'undefined'; | |
// Render the Dialog only on the client side | |
const renderDialog = isClient && isOpen && dialogContent.component && ( | |
<Dialog open={ isOpen } onClose={ closeDialog }> | |
{ React.createElement( dialogContent.component, { ...dialogContent.props } ) } | |
<Button onClick={ closeDialog }>Close Dialog</Button> | |
</Dialog> | |
); | |
return ( | |
<DialogContext.Provider value={ { showDialog, closeDialog, isOpen, dialogContent } }> | |
{ isClient && children } | |
{ renderDialog } | |
</DialogContext.Provider> | |
); | |
}; | |
export default DialogProvider; | |
export const useDialog = (): DialogCtx => { | |
const context = useContext( DialogContext ); | |
invariant( context, 'useDialog must be used within a DialogProvider' ); | |
return context; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment