one
Version:
One is a new React Framework that makes Vite serve both native and web.
63 lines (51 loc) • 1.67 kB
text/typescript
import { type NavigationProp, type NavigationState, useNavigation } from '@react-navigation/native'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useOneRouter } from '../router/router'
type GenericNavigation = NavigationProp<ReactNavigation.RootParamList> & {
getState(): NavigationState | undefined
}
/** Returns a callback which is invoked when the navigation state has loaded. */
export function useLoadedNavigation() {
const { navigationRef } = useOneRouter()
const navigation = useNavigation()
const isMounted = useRef(true)
const pending = useRef<((navigation: GenericNavigation) => void)[]>([])
useEffect(() => {
isMounted.current = true
return () => {
isMounted.current = false
}
}, [])
const flush = useCallback(() => {
if (isMounted.current) {
const pendingCallbacks = pending.current
pending.current = []
pendingCallbacks.forEach((callback) => {
callback(navigation as GenericNavigation)
})
}
}, [navigation])
useEffect(() => {
if (navigationRef.current) {
flush()
}
}, [flush, navigationRef])
const push = useCallback(
(fn: (navigation: GenericNavigation) => void) => {
pending.current.push(fn)
if (navigationRef.current) {
flush()
}
},
[flush, navigationRef]
)
return push
}
export function useOptionalNavigation(): GenericNavigation | null {
const [navigation, setNavigation] = useState<GenericNavigation | null>(null)
const loadNavigation = useLoadedNavigation()
useEffect(() => {
loadNavigation((nav) => setNavigation(nav))
}, [loadNavigation])
return navigation
}