Skip to content

Instantly share code, notes, and snippets.

@AngelKrak
Created August 24, 2024 04:27
Show Gist options
  • Select an option

  • Save AngelKrak/c3863e86cc46a6a6799539559ea58697 to your computer and use it in GitHub Desktop.

Select an option

Save AngelKrak/c3863e86cc46a6a6799539559ea58697 to your computer and use it in GitHub Desktop.
TypeScript utility function for managing and updating React Navigation state. Supports adding and removing routes, optional parameters, and a flexible reset mechanism with custom options like retaining the initial route. Ideal for dynamic navigation flows in React Native applications
import {
CommonActions,
NavigationContainerRef,
ParamListBase,
} from '@react-navigation/native';
interface UpdateNavigationStateOptions {
routesToAdd?: (string | {name: string; params?: object})[];
paramsToAdd?: object[];
routesToRemove?: string[];
resetAll?: boolean;
keepFirstRoute?: boolean;
}
/**
* Generates a unique key for a route.
*
* @param {string} name - The name of the route.
* @returns {string} A unique key for the route.
*/
function generateRouteKey(name: string): string {
return `${name}-${Math.random().toString(36).substr(2, 9)}`;
}
/**
* Updates the navigation state with new routes and custom options.
*
* @param {NavigationContainerRef<ParamListBase>} navigation - Navigation object provided by React Navigation.
* @param {UpdateNavigationStateOptions} options - Options for updating the navigation state.
*
* @example
* // Adds the routes 'Home' and 'Profile', with the first parameter empty and the second with an object { user: 'jane' },
* // removes the route 'Login', and performs a total reset by removing all routes except the first one.
* updateNavigationState(navigation, {
* routesToAdd: ["Home", "Profile"],
* paramsToAdd: [{}, { user: 'jane' }],
* routesToRemove: ["Login"],
* resetAll: true,
* keepFirstRoute: false, // Determines whether the first route is kept when performing a total reset
* });
*/
function updateNavigationState(
navigation: NavigationContainerRef<ParamListBase>,
{
routesToAdd = [],
paramsToAdd = [],
routesToRemove = [],
resetAll = false,
keepFirstRoute = true, // Default is true, which means the first route will be kept
}: UpdateNavigationStateOptions,
) {
if (!navigation) throw new Error('Navigation is required');
return navigation.dispatch(state => {
let routes = [...state.routes];
// Perform a total reset if necessary
if (resetAll) {
routes = keepFirstRoute ? [routes[0]] : []; // Keep the first route if keepFirstRoute is true, otherwise empty the routes
}
// Remove specific routes
if (routesToRemove.length > 0) {
routesToRemove.forEach(routeName => {
routes = routes.filter(route => route.name !== routeName);
});
}
// Add new routes
if (routesToAdd.length > 0) {
routesToAdd.forEach((route, index) => {
if (typeof route === 'string') {
const params = paramsToAdd?.[index] || {}; // Get parameters if available
routes.push({
key: generateRouteKey(route),
name: route,
params,
});
} else if (typeof route === 'object' && route.name) {
routes.push({
key: generateRouteKey(route.name),
...route,
});
}
});
}
return CommonActions.reset({
...state,
routes,
index: routes.length - 1,
});
});
}
export default updateNavigationState;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment