You can opt-in to having the modal react to changes in the URL, and push changes to the URL as necessary. This would allow you to directly link to an open modal. There are two ways to do this — using the native browser history API, or your app's existing router.
To allow the modal to handle URL changes using the History API, pass handleParamChange
to the ModalProvider
. The ?modal=
param will appear in the URL as modals are navigated. Modals will also react to external changes to this param, so your app can load with an open modal. This enables you to directly link to modal content.
import { ModalProvider } from '@faceless-ui/modal'; export const MyApp = (props) => { return ( <ModalProvider handleParamChange> ... </ModalProvider> ); }
If your app already uses a router, send a callback function to handleParamChange
instead. Here are some examples using common router libraries.
import React, { useCallback } from 'react'; import { ModalProvider } from '@faceless-ui/modal'; import Router from 'next/router'; export default App = () => { const handleParamChange = useCallback((incomingSlug) => { Router.push({ query: { modal: incomingSlug }, }) }, []); return ( <ModalProvider handleParamChange={handleParamChange}> ... </ModalProvider> ) }
import React, { useCallback } from 'react'; import { ModalProvider } from '@faceless-ui/modal'; import { useLocation, useHistory } from 'react-router-dom'; import qs from 'qs'; export default App = () => { const history = useHistory(); const { url, search } = useLocation(); const handleParamChange = useCallback((incomingSlug) => { const withChangedSlug = qs.parse(search, { ignoreQueryPrefix: true }); withChangedSlug.slug = incomingSlug; newSearchString = qs.stringify(withChangedSlug, { encode: false }); history.push(\`\${url}\${newSearchString}\`) }, [url, search, history]); return ( <ModalProvider handleParamChange={handleParamChange}> ... </ModalProvider> ) }
Often you will want to close all modals on route changes. This is a very common pattern that is very easily solved by tying into your apps existing router, and firing the closeAllModals
method at the right time.
import React from 'react'; import { useModal } from "@faceless-ui/modal"; import { Router } from "next/router"; import { useEffect } from "react" export const CloseModalOnRouteChange = () => { const { closeAllModals } = useModal(); useEffect(() => { Router.events.on('routeChangeComplete', () => { closeAllModals(); }); }, [closeAllModals]); return null; }