UNPKG

@react-navigation/core

Version:

Core utilities for building navigators

111 lines (107 loc) 3.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getActionFromState = getActionFromState; function getActionFromState(state, options) { // Create a normalized configs object which will be easier to use const normalizedConfig = options ? createNormalizedConfigItem(options) : {}; const routes = state.index != null ? state.routes.slice(0, state.index + 1) : state.routes; if (routes.length === 0) { return undefined; } if (!(routes.length === 1 && routes[0].key === undefined || routes.length === 2 && routes[0].key === undefined && routes[0].name === normalizedConfig?.initialRouteName && routes[1].key === undefined)) { return { type: 'RESET', payload: state }; } const route = state.routes[state.index ?? state.routes.length - 1]; let current = route?.state; let config = normalizedConfig?.screens?.[route?.name]; let params = { ...route.params }; const payload = route ? { name: route.name, path: route.path, params } : undefined; // If the screen contains a navigator, pop other screens to navigate to it // This avoid pushing multiple instances of navigators onto a stack // // For example: // - RootStack // - BottomTabs // - SomeScreen // // In this case, if deep linking to `BottomTabs`, we should pop `SomeScreen` // Otherwise, we'll end up with 2 instances of `BottomTabs` in the stack // // There are 2 ways we can detect if a screen contains a navigator: // - The route contains nested state in `route.state` // - Nested screens are defined in the config if (payload && config?.screens && Object.keys(config.screens).length) { payload.pop = true; } while (current) { if (current.routes.length === 0) { return undefined; } const routes = current.index != null ? current.routes.slice(0, current.index + 1) : current.routes; const route = routes[routes.length - 1]; // Explicitly set to override existing value when merging params Object.assign(params, { initial: undefined, screen: undefined, params: undefined, state: undefined }); if (routes.length === 1 && routes[0].key === undefined) { params.initial = true; params.screen = route.name; } else if (routes.length === 2 && routes[0].key === undefined && routes[0].name === config?.initialRouteName && routes[1].key === undefined) { params.initial = false; params.screen = route.name; } else { params.state = current; break; } if (route.state) { params.params = { ...route.params }; params.pop = true; params = params.params; } else { params.path = route.path; params.params = route.params; } current = route.state; config = config?.screens?.[route.name]; if (config?.screens && Object.keys(config.screens).length) { params.pop = true; } } if (payload?.params.screen || payload?.params.state) { payload.pop = true; } if (!payload) { return; } // Try to construct payload for a `NAVIGATE` action from the state // This lets us preserve the navigation state and not lose it return { type: 'NAVIGATE', payload }; } const createNormalizedConfigItem = config => typeof config === 'object' && config != null ? { initialRouteName: config.initialRouteName, screens: config.screens != null ? createNormalizedConfigs(config.screens) : undefined } : {}; const createNormalizedConfigs = options => Object.entries(options).reduce((acc, [k, v]) => { acc[k] = createNormalizedConfigItem(v); return acc; }, {}); //# sourceMappingURL=getActionFromState.js.map