useIsFocused
Since useIsFocused()
only applicable on Native, you can replace it with a custom function on Web.
Create your exports​
hooks/use-is-focused.ts
ts
export {useIsFocused } from '@react-navigation/native'
ts
export {useIsFocused } from '@react-navigation/native'
hooks/use-is-focused.web.ts
ts
export functionuseIsFocused () {return true}
ts
export functionuseIsFocused () {return true}
On Web, screens are always focused when they're mounted.
Import your file​
ts
import { useIsFocused } from 'hooks/use-is-focused'
ts
import { useIsFocused } from 'hooks/use-is-focused'
Custom Web Logic​
This section is a little more advanced. It's relevant if you're using modals with Next Router.
In the above example, we always return true
on Web.
One exception might be if there is a shallow routed modal on top of a screen.
For example, say that you have an EditArtist
modal that shows when the URL contains a query param like /@djkhaled?showsEditModal=true
.
If you want to implement this logic, you could do it yourself on Web using a combination of React Context and checking query params with useRouter
from next/router
.
Create a context​
First, in a file called context/modal-screen
create your ModalScreenContext
. This will let screens detect if they are a modal or not.
ts
import {createContext } from 'react'Âexport constModalScreenContext =createContext (false)
ts
import {createContext } from 'react'Âexport constModalScreenContext =createContext (false)
Then, your actual Next.js page could look something like this:
tsx
// pages/artist/[slug].tsximport { ModalScreenContext } from 'context/modal-screen'import { useRouter } from 'next/router'export default function ArtistPage() {const router = useRouter()return (<><ArtistScreen /><ModalScreenContext.Provider value={true}>{router?.query?.showsEditModal && <EditArtistModal />}</ModalScreenContext.Provider></>)}
tsx
// pages/artist/[slug].tsximport { ModalScreenContext } from 'context/modal-screen'import { useRouter } from 'next/router'export default function ArtistPage() {const router = useRouter()return (<><ArtistScreen /><ModalScreenContext.Provider value={true}>{router?.query?.showsEditModal && <EditArtistModal />}</ModalScreenContext.Provider></>)}
Notice that the EditArtistModal
is wrapped with the ModalScreenContext.Provider
, and the value
is true
.
This means that any component inside of EditArtistModal
will know it is a modal, whereas every component inside of ArtistScreen
will know it is not a modal.
Use the context​
If you stick to the pattern of always including the word modal
in the URL, you can use the useRouter
hook to check if the URL contains the query param:
The logic for useIsFocused
should now be this: your hook is focused if one of these conditions is true:
- the hook is inside of a (mounted) modal, or
- the hook is not a modal, and there is no modal mounted a. Why? If this hook is not in a modal, but a modal is mounted, then that means that this hook is underneath the modal, and thus not focused.
ts
import {useContext } from 'react'import {useRouter } from 'next/router'import {ModalScreenContext } from './context/modal-screen'Âexport functionuseIsFocused () {const {query } =useRouter ()constisModalScreen =useContext (ModalScreenContext )Âif (isModalScreen ) {return true}ÂconstisThereAModalVisible =query &&Object .keys (query ).some ((key ) =>key .toLowerCase ().includes ('modal'))Âreturn !isThereAModalVisible }
ts
import {useContext } from 'react'import {useRouter } from 'next/router'import {ModalScreenContext } from './context/modal-screen'Âexport functionuseIsFocused () {const {query } =useRouter ()constisModalScreen =useContext (ModalScreenContext )Âif (isModalScreen ) {return true}ÂconstisThereAModalVisible =query &&Object .keys (query ).some ((key ) =>key .toLowerCase ().includes ('modal'))Âreturn !isThereAModalVisible }
To use this as a repeatable method, it's important that you always use the word modal
as a query param to denote that a modal is open.