-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #43013 from Expensify/Rory-ModalContextProvider
Use modal context provider to fix useResponsiveLayout (cherry picked from commit 87db18a)
- Loading branch information
1 parent
0f14205
commit feadce2
Showing
10 changed files
with
175 additions
and
112 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import {createContext} from 'react'; | ||
import type ModalType from '@src/types/utils/ModalType'; | ||
|
||
type ModalContextType = { | ||
// The type of the currently displayed modal, or undefined if there is no currently displayed modal. | ||
// Note that React Native can only display one modal at a time. | ||
activeModalType?: ModalType; | ||
}; | ||
|
||
// This context is meant to inform modal children that they are rendering in a modal (and what type of modal they are rendering in) | ||
// Note that this is different than ONYXKEYS.MODAL.isVisible data point in that that is a global variable for whether a modal is visible or not, | ||
// whereas this context is provided by the BaseModal component, and thus is only available to components rendered inside a modal. | ||
const ModalContext = createContext<ModalContextType>({}); | ||
|
||
export default ModalContext; |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import type {EventListenerCallback, NavigationContainerEventMap} from '@react-navigation/native'; | ||
import type {NavigationState} from '@react-navigation/routers'; | ||
import {useCallback, useSyncExternalStore} from 'react'; | ||
import {navigationRef} from '@libs/Navigation/Navigation'; | ||
|
||
/** | ||
* This hook is a replacement for `useNavigationState` for nested navigators. | ||
* If `useNavigationState` is used within a nested navigator then the state that's returned is the state of the nearest parent navigator, | ||
* not the root navigator state representing the whole app's navigation tree. | ||
* | ||
* Use with caution, because re-rendering any component every time the root navigation state changes can be very costly for performance. | ||
* That's why the selector is mandatory. | ||
*/ | ||
function useRootNavigationState<T>(selector: (state: NavigationState) => T): T | undefined { | ||
const getSnapshot = useCallback(() => { | ||
if (!navigationRef?.current) { | ||
return; | ||
} | ||
return selector(navigationRef.current.getRootState()); | ||
}, [selector]); | ||
|
||
const subscribeToRootState = useCallback((callback: EventListenerCallback<NavigationContainerEventMap, 'state'>) => { | ||
const unsubscribe = navigationRef?.current?.addListener('state', callback); | ||
return () => unsubscribe?.(); | ||
}, []); | ||
|
||
return useSyncExternalStore(subscribeToRootState, getSnapshot); | ||
} | ||
|
||
export default useRootNavigationState; |
Oops, something went wrong.