Skip to content

Instantly share code, notes, and snippets.

@emeraldsanto
Last active August 4, 2020 01:53
Show Gist options
  • Save emeraldsanto/efedef136682fe60f22a613aba711d1d to your computer and use it in GitHub Desktop.
Save emeraldsanto/efedef136682fe60f22a613aba711d1d to your computer and use it in GitHub Desktop.
Module exposing custom wrappers over plain NavigationContainer functions to enable navigation throughout the application
import { log } from "@lib/Logger";
import { createRef, ReactNode } from "react";
import { StackScreenArguments } from "./NavigationScreen";
import { DrawerActions, EventListenerCallback, NavigationContainerEventMap, NavigationContainerRef, NavigationState, PartialState, StackActions } from "@react-navigation/native";
/**
* Reference to the root `NavigationContainer` component. Used to dispatch
* actions and commands from anywhere within the app.
*/
export const navigationRef = createRef<NavigationContainerRef>();
/**
* Dispatches a `navigate` navigation action to the provided route name, along with the provided payload.
* @param {string} routeName - The name of the route to navigate to.
* @param {Object} [params] - The payload to send to the route.
* @param {boolean} [shouldPush] - Wether or not to navigate to the route if one with the same name is already present on the stack
*/
export function navigate<TName extends keyof StackScreenArguments>(routeName: TName, params?: StackScreenArguments[TName]) {
if (!navigationRef.current) {
log("Navigation", "Tried to navigate without a navigator ref", "warn");
return;
}
navigationRef.current.navigate(routeName as string, params ?? {});
}
/**
* Dispatches a `push` navigation action to the provided route name, along with the provided payload
* @param routeName The name of the route to navigate to.
* @param params The payload to send to the route.
*/
export function push<TName extends keyof StackScreenArguments>(routeName: TName, params?: StackScreenArguments[TName]) {
if (!navigationRef.current) {
log("Navigation", "Tried to push without a navigator ref", "warn");
return;
}
navigationRef.current.dispatch(
StackActions.push(routeName as string, params ?? {})
);
}
/**
* Resets the navigation state so that the provided route is the only active one.
* @param routeName The name of the route to navigate to
* @param params The payload to send to the route
*/
export function reset(state: NavigationState | PartialState<NavigationState>) {
if (!navigationRef.current) {
log("Navigation", "Tried to reset without a navigator ref", "warn");
return;
}
navigationRef.current.reset(state);
}
/**
* Dispatches a `back` navigation event to go back to the previous screen.
*/
export function goBack() {
if (!navigationRef.current) {
log("Navigation", "Tried to go back without a navigator ref", "warn");
return;
}
else if (navigationRef.current.canGoBack()) {
navigationRef.current.goBack();
}
else {
log("Navigation", "Tried to go back without any previous screen", "warn");
}
}
/**
* Opens the drawer
*/
export function openDrawer() {
if (!navigationRef.current) {
log("Navigation", "Tried to open drawer without a navigator ref", "warn");
return;
}
navigationRef.current.dispatch(
DrawerActions.openDrawer()
);
}
/**
* Closes the drawer
*/
export function closeDrawer() {
if (!navigationRef.current) {
log("Navigation", "Tried to close drawer without a navigator ref", "warn");
return;
}
navigationRef.current.dispatch(
DrawerActions.closeDrawer()
);
}
/**
* Toggles the drawer
*/
export function toggleDrawer() {
if (!navigationRef.current) {
log("Navigation", "Tried to toggle drawer without a navigator ref", "warn");
return;
}
navigationRef.current.dispatch(
DrawerActions.toggleDrawer()
);
}
/**
* Subscribes to a navigation event.
* @param eventName The name of the event to subscribe to.
* @param callback The function to call when said event occurs.
*/
export function addNavigationListener<T extends "state" | "options">(eventName: T, callback: EventListenerCallback<NavigationContainerEventMap, T>) {
if (!navigationRef.current) {
return () => { };
}
return navigationRef.current?.addListener(eventName, callback);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment