|
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; |