From 535c6b954e145001c9d0d8128a73c49613f0f9bb Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 14 May 2025 17:15:37 +0200 Subject: [PATCH 1/4] add useCustomHistoryParam --- src/CONST.ts | 2 + .../addCustomHistoryRouterExtension.ts | 146 ++++++++++++++++++ .../AppNavigator/customHistory/index.ts | 2 + .../AppNavigator/customHistory/types.ts | 18 +++ .../customHistory/useCustomHistoryParam.ts | 42 +++++ .../index.tsx | 3 +- .../Navigation/linkingConfig/HISTORY_PARAM.ts | 5 + .../RELATIONS/SCREEN_TO_HISTORY_PARAM.ts | 22 +++ src/libs/Navigation/linkingConfig/config.ts | 3 + .../helpers/getHistoryParamParse.ts | 5 + src/libs/Navigation/types.ts | 1 + .../AddDelegate/ConfirmDelegatePage.tsx | 14 +- 12 files changed, 253 insertions(+), 10 deletions(-) create mode 100644 src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts create mode 100644 src/libs/Navigation/AppNavigator/customHistory/index.ts create mode 100644 src/libs/Navigation/AppNavigator/customHistory/types.ts create mode 100644 src/libs/Navigation/AppNavigator/customHistory/useCustomHistoryParam.ts create mode 100644 src/libs/Navigation/linkingConfig/HISTORY_PARAM.ts create mode 100644 src/libs/Navigation/linkingConfig/RELATIONS/SCREEN_TO_HISTORY_PARAM.ts create mode 100644 src/libs/Navigation/linkingConfig/helpers/getHistoryParamParse.ts diff --git a/src/CONST.ts b/src/CONST.ts index 9013873bf3839..078a070941e99 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -5108,11 +5108,13 @@ const CONST = { REPLACE: 'REPLACE', PUSH: 'PUSH', NAVIGATE: 'NAVIGATE', + SET_PARAMS: 'SET_PARAMS', /** These action types are custom for RootNavigator */ SWITCH_POLICY_ID: 'SWITCH_POLICY_ID', DISMISS_MODAL: 'DISMISS_MODAL', OPEN_WORKSPACE_SPLIT: 'OPEN_WORKSPACE_SPLIT', + SET_HISTORY_PARAM: 'SET_HISTORY_PARAM', }, }, TIME_PERIOD: { diff --git a/src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts b/src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts new file mode 100644 index 0000000000000..78ac7f5beab06 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts @@ -0,0 +1,146 @@ +import {CommonActions, findFocusedRoute} from '@react-navigation/native'; +import type {ParamListBase, PartialState, Router, RouterConfigOptions, StackActionType} from '@react-navigation/native'; +import type {PlatformStackNavigationState, PlatformStackRouterFactory, PlatformStackRouterOptions} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {SetParamsAction} from '@libs/Navigation/types'; +import CONST from '@src/CONST'; +import SCREEN_TO_HISTORY_PARAM from '@src/libs/Navigation/linkingConfig/RELATIONS/SCREEN_TO_HISTORY_PARAM'; +import type {Screen} from '@src/SCREENS'; +import type {HistoryStackNavigatorAction, SetHistoryParamActionType} from './types'; + +const CUSTOM_HISTORY_PREFIX = 'CUSTOM_HISTORY_'; + +function isSetParamsAction(action: HistoryStackNavigatorAction): action is SetParamsAction { + return action.type === CONST.NAVIGATION.ACTION_TYPE.SET_PARAMS; +} + +function isSetHistoryParamAction(action: HistoryStackNavigatorAction): action is SetHistoryParamActionType { + return action.type === CONST.NAVIGATION.ACTION_TYPE.SET_HISTORY_PARAM; +} + +// The history can be anything. For now, string is enough but we can extend it to include more data if necessary. +function getCustomHistoryEntry(routeName: string) { + return `${CUSTOM_HISTORY_PREFIX}-${routeName}`; +} + +/** + * Higher-order function that extends the React Navigation stack router with custom history functionality. + * It allows tracking and managing navigation history entries that are not determined by the routes of navigator. + * The extension adds support for custom history entries through route params and maintains a history stack + * that can be manipulated independently of the navigation state. + * + * @param originalStackRouter - The original stack router function to be extended + * @returns Enhanced router with custom history functionality + */ + +function addCustomHistoryRouterExtension( + originalRouter: PlatformStackRouterFactory, +) { + return (options: RouterOptions): Router, CommonActions.Action | StackActionType | HistoryStackNavigatorAction> => { + const router = originalRouter(options); + + const enhanceStateWithHistory = (state: PlatformStackNavigationState) => { + return { + ...state, + history: state.routes.map((route) => route.key), + }; + }; + + // Override methods to enhance state with history + const getInitialState = (configOptions: RouterConfigOptions) => { + const state = router.getInitialState(configOptions); + return enhanceStateWithHistory(state); + }; + + const getRehydratedState = (partialState: PartialState>, configOptions: RouterConfigOptions) => { + const state = router.getRehydratedState(partialState, configOptions); + const stateWithInitialHistory = enhanceStateWithHistory(state); + + const focusedRoute = findFocusedRoute(state); + + // There always be a focused route in the state. It's for type safety. + if (!focusedRoute) { + return stateWithInitialHistory; + } + + const customHistoryParamName = SCREEN_TO_HISTORY_PARAM[focusedRoute.name as Screen]; + + if ( + // The custom history param name should be defined + typeof customHistoryParamName === 'string' && + // Params for the focused route should be defined + focusedRoute.params && + // The custom history param with given name should be defined in the params + customHistoryParamName in focusedRoute.params && + // The custom history param should be set to true + (focusedRoute.params as Record)[customHistoryParamName] && + // The last history entry should not be the custom history entry for the focused route to avoid duplication + stateWithInitialHistory.history.at(-1) !== getCustomHistoryEntry(focusedRoute.name) + ) { + // Add the custom history entry to the initial history + stateWithInitialHistory.history = [...stateWithInitialHistory.history, getCustomHistoryEntry(focusedRoute.name)]; + } + + return stateWithInitialHistory; + }; + + const getStateForAction = ( + state: PlatformStackNavigationState, + action: CommonActions.Action | StackActionType | HistoryStackNavigatorAction, + configOptions: RouterConfigOptions, + ) => { + // We want to set the right param and then update the history + if (isSetHistoryParamAction(action)) { + // Start with updating the param. + const setParamsAction = CommonActions.setParams({[action.payload.key]: action.payload.value}); + const stateWithUpdatedParams = router.getStateForAction(state, setParamsAction, configOptions); + + // This shouldn't ever happen as the history should be always defined. It's for type safety. + if (!stateWithUpdatedParams?.history) { + return stateWithUpdatedParams; + } + + // If it's set to true, we need to add the history entry if it's not already there. + if (action.payload.value && stateWithUpdatedParams.history.at(-1) !== getCustomHistoryEntry(action.payload.key)) { + return {...stateWithUpdatedParams, history: [...stateWithUpdatedParams.history, getCustomHistoryEntry(action.payload.key)]}; + } + + // If it's set to false, we need to remove the history entry if it's there. + if (!action.payload.value) { + return {...stateWithUpdatedParams, history: stateWithUpdatedParams.history.filter((entry) => entry !== getCustomHistoryEntry(action.payload.key))}; + } + + // Else, do not change history. + return stateWithUpdatedParams; + } + + const newState = router.getStateForAction(state, action, configOptions); + + // If the action was not handled, return null. + if (!newState) { + return null; + } + + // If the action was a setParams action, we need to preserve the history. + if (isSetParamsAction(action) && state.history) { + return { + ...newState, + history: [...state.history], + }; + } + + // Handle every other action. + // @ts-expect-error newState can be partial or not. But getRehydratedState will handle it correctly even if the stale === false. + // And we need to update the history if routes have changed. + return getRehydratedState(newState, configOptions); + }; + + return { + ...router, + getInitialState, + getRehydratedState, + getStateForAction, + }; + }; +} + +export default addCustomHistoryRouterExtension; diff --git a/src/libs/Navigation/AppNavigator/customHistory/index.ts b/src/libs/Navigation/AppNavigator/customHistory/index.ts new file mode 100644 index 0000000000000..cfea975fcb72a --- /dev/null +++ b/src/libs/Navigation/AppNavigator/customHistory/index.ts @@ -0,0 +1,2 @@ +export {default as addCustomHistoryRouterExtension} from './addCustomHistoryRouterExtension'; +export {default as useCustomHistoryParam} from './useCustomHistoryParam'; diff --git a/src/libs/Navigation/AppNavigator/customHistory/types.ts b/src/libs/Navigation/AppNavigator/customHistory/types.ts new file mode 100644 index 0000000000000..cd84971f4edf3 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/customHistory/types.ts @@ -0,0 +1,18 @@ +import type {CommonActions, StackActionType} from '@react-navigation/native'; +import type CONST from '@src/CONST'; + +type HistoryStackNavigatorAction = CommonActions.Action | StackActionType | HistoryStackNavigatorActionType; + +type HistoryStackNavigatorActionType = { + type: typeof CONST.NAVIGATION.ACTION_TYPE.SET_HISTORY_PARAM; + payload: { + key: string; + value: boolean; + }; +}; + +type SetHistoryParamActionType = HistoryStackNavigatorAction & { + type: typeof CONST.NAVIGATION.ACTION_TYPE.SET_HISTORY_PARAM; +}; + +export type {HistoryStackNavigatorAction, HistoryStackNavigatorActionType, SetHistoryParamActionType}; diff --git a/src/libs/Navigation/AppNavigator/customHistory/useCustomHistoryParam.ts b/src/libs/Navigation/AppNavigator/customHistory/useCustomHistoryParam.ts new file mode 100644 index 0000000000000..e7f657982e721 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/customHistory/useCustomHistoryParam.ts @@ -0,0 +1,42 @@ +import {useNavigation, useRoute} from '@react-navigation/native'; +import SCREEN_TO_HISTORY_PARAM from '@libs/Navigation/linkingConfig/RELATIONS/SCREEN_TO_HISTORY_PARAM'; +import CONST from '@src/CONST'; +import type {Screen} from '@src/SCREENS'; + +/** + * Custom hook for managing navigation history entries + * It works as useState but it pushes the history entry when the value is true. + * The value will change to false if the user navigates back with the browser back button. + * It uses screen param to store the information and make it visible in the url so the state persist after refreshing the page. + * + * @returns A tuple containing [historyParam, setHistoryParam] where: + * - historyParam: boolean | undefined - The current state of the history parameter + * - setHistoryParam: (value: boolean) => void - Function to update the history parameter + */ +function useCustomHistoryParam() { + const navigation = useNavigation(); + const route = useRoute(); + const historyParamName = SCREEN_TO_HISTORY_PARAM[route.name as Screen]; + + if (!historyParamName || typeof historyParamName !== 'string') { + throw new Error(`Screen ${route.name} does not have a history param. You can use this hook only on the screens that have one defined in SCREEN_TO_HISTORY_PARAM.`); + } + + const historyParam = route.params && (route.params as Record)[historyParamName] ? ((route.params as Record)[historyParamName] as boolean) : false; + + if (typeof historyParam !== 'boolean') { + throw new Error(`The history param ${historyParamName} is not a boolean. Make sure that you used getHistoryParamParse for this screen in linkingConfig/config.ts`); + } + + return [ + historyParam, + (value: boolean) => { + navigation.dispatch({ + type: CONST.NAVIGATION.ACTION_TYPE.SET_HISTORY_PARAM, + payload: {key: historyParamName, value}, + }); + }, + ] as const; +} + +export default useCustomHistoryParam; diff --git a/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.tsx b/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.tsx index fa45e5834aaa6..e98de444ad714 100644 --- a/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.tsx +++ b/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.tsx @@ -3,6 +3,7 @@ import {StackRouter, useNavigationBuilder} from '@react-navigation/native'; import type {StackNavigationEventMap, StackNavigationOptions} from '@react-navigation/stack'; import {StackView} from '@react-navigation/stack'; import React, {useMemo} from 'react'; +import {addCustomHistoryRouterExtension} from '@libs/Navigation/AppNavigator/customHistory'; import convertToWebNavigationOptions from '@libs/Navigation/PlatformStackNavigation/navigationOptions/convertToWebNavigationOptions'; import type { CreatePlatformStackNavigatorComponentOptions, @@ -18,7 +19,7 @@ function createPlatformStackNavigatorComponent, ) { - const createRouter = options?.createRouter ?? StackRouter; + const createRouter = addCustomHistoryRouterExtension(options?.createRouter ?? StackRouter); const useCustomState = options?.useCustomState ?? (() => undefined); const defaultScreenOptions = options?.defaultScreenOptions; const ExtraContent = options?.ExtraContent; diff --git a/src/libs/Navigation/linkingConfig/HISTORY_PARAM.ts b/src/libs/Navigation/linkingConfig/HISTORY_PARAM.ts new file mode 100644 index 0000000000000..9ea2bc1aa1855 --- /dev/null +++ b/src/libs/Navigation/linkingConfig/HISTORY_PARAM.ts @@ -0,0 +1,5 @@ +const HISTORY_PARAM = { + SHOW_VALIDATE_CODE_ACTION_MODAL: 'showValidateActionModal', +} as const; + +export default HISTORY_PARAM; diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/SCREEN_TO_HISTORY_PARAM.ts b/src/libs/Navigation/linkingConfig/RELATIONS/SCREEN_TO_HISTORY_PARAM.ts new file mode 100644 index 0000000000000..356dc2e49ccd0 --- /dev/null +++ b/src/libs/Navigation/linkingConfig/RELATIONS/SCREEN_TO_HISTORY_PARAM.ts @@ -0,0 +1,22 @@ +import type {NavigatorScreenParams} from '@react-navigation/native'; +import HISTORY_PARAM from '@libs/Navigation/linkingConfig/HISTORY_PARAM'; +import type {RootNavigatorParamList} from '@libs/Navigation/types'; +import type {Screen} from '@src/SCREENS'; +import SCREENS from '@src/SCREENS'; + +type DeepPairsOf = DeepPairsForScreen; + +type DeepPairsForScreen = Key extends keyof ParamList ? (ParamList[Key] extends NavigatorScreenParams ? DeepPairsOf : [Key, keyof ParamList[Key]]) : never; + +type DeepPairsOfRoot = DeepPairsOf; + +type ScreenToHistoryParamMap = Partial<{ + [TScreen in Screen]: Extract[1]; +}>; + +// This file maps screens to their history parameters +const SCREEN_TO_HISTORY_PARAM: ScreenToHistoryParamMap = { + [SCREENS.SETTINGS.DELEGATE.DELEGATE_CONFIRM]: HISTORY_PARAM.SHOW_VALIDATE_CODE_ACTION_MODAL, +}; + +export default SCREEN_TO_HISTORY_PARAM; diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 9f24045bb6f4f..d49874d82c2c2 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -6,6 +6,8 @@ import NAVIGATORS from '@src/NAVIGATORS'; import ROUTES from '@src/ROUTES'; import type {Screen} from '@src/SCREENS'; import SCREENS from '@src/SCREENS'; +import getHistoryParamParse from './helpers/getHistoryParamParse'; +import HISTORY_PARAM from './HISTORY_PARAM'; // Moved to a separate file to avoid cyclic dependencies. const config: LinkingOptions['config'] = { @@ -328,6 +330,7 @@ const config: LinkingOptions['config'] = { path: ROUTES.SETTINGS_DELEGATE_CONFIRM.route, parse: { login: (login: string) => decodeURIComponent(login), + ...getHistoryParamParse(HISTORY_PARAM.SHOW_VALIDATE_CODE_ACTION_MODAL), }, }, [SCREENS.SETTINGS.PROFILE.STATUS]: { diff --git a/src/libs/Navigation/linkingConfig/helpers/getHistoryParamParse.ts b/src/libs/Navigation/linkingConfig/helpers/getHistoryParamParse.ts new file mode 100644 index 0000000000000..7bae4da41012d --- /dev/null +++ b/src/libs/Navigation/linkingConfig/helpers/getHistoryParamParse.ts @@ -0,0 +1,5 @@ +const getHistoryParamParse = (historyParamName: string) => ({ + [historyParamName]: (value: string) => value === 'true', +}); + +export default getHistoryParamParse; diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 8e0415879be33..cc6a0f1365af8 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -2099,4 +2099,5 @@ export type { WorkspaceScreenName, SettingsTabScreenName, TestDriveDemoNavigatorParamList, + SetParamsAction, }; diff --git a/src/pages/settings/Security/AddDelegate/ConfirmDelegatePage.tsx b/src/pages/settings/Security/AddDelegate/ConfirmDelegatePage.tsx index da6b3dd558ea9..ec4c275a7f0ac 100644 --- a/src/pages/settings/Security/AddDelegate/ConfirmDelegatePage.tsx +++ b/src/pages/settings/Security/AddDelegate/ConfirmDelegatePage.tsx @@ -1,4 +1,4 @@ -import React, {useEffect, useState} from 'react'; +import React, {useState} from 'react'; import type {ValueOf} from 'type-fest'; import Button from '@components/Button'; import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper'; @@ -13,6 +13,7 @@ import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import {formatPhoneNumber} from '@libs/LocalePhoneNumber'; +import {useCustomHistoryParam} from '@libs/Navigation/AppNavigator/customHistory'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; @@ -24,21 +25,17 @@ import DelegateMagicCodeModal from './DelegateMagicCodeModal'; type ConfirmDelegatePageProps = PlatformStackScreenProps; -function ConfirmDelegatePage({route, navigation}: ConfirmDelegatePageProps) { +function ConfirmDelegatePage({route}: ConfirmDelegatePageProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const login = route.params.login; const role = route.params.role as ValueOf; - const showValidateActionModal = route.params.showValidateActionModal === 'true'; const {isOffline} = useNetwork(); const [shouldDisableModalAnimation, setShouldDisableModalAnimation] = useState(true); - const [shouldShowLoading, setShouldShowLoading] = useState(showValidateActionModal ?? false); - const [isValidateCodeActionModalVisible, setIsValidateCodeActionModalVisible] = useState(showValidateActionModal ?? false); - useEffect(() => { - navigation.setParams({showValidateActionModal: String(isValidateCodeActionModalVisible)}); - }, [isValidateCodeActionModalVisible, navigation]); + const [isValidateCodeActionModalVisible, setIsValidateCodeActionModalVisible] = useCustomHistoryParam(); + const [shouldShowLoading, setShouldShowLoading] = useState(isValidateCodeActionModalVisible ?? false); const personalDetails = getPersonalDetailByEmail(login); const avatarIcon = personalDetails?.avatar ?? FallbackAvatar; @@ -93,7 +90,6 @@ function ConfirmDelegatePage({route, navigation}: ConfirmDelegatePageProps) { // We should disable the animation initially and only enable it when the user manually opens the modal // to ensure it appears immediately when refreshing the page. disableAnimation={shouldDisableModalAnimation} - shouldHandleNavigationBack login={login} role={role} onClose={() => { From 6c87623fa4ea0679d869857652b5ba10a405cb69 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Thu, 15 May 2025 14:12:14 +0200 Subject: [PATCH 2/4] fix CUSTOM_HISTORY_PREFIX --- .../customHistory/addCustomHistoryRouterExtension.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts b/src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts index 78ac7f5beab06..0b16e42c8e51e 100644 --- a/src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts +++ b/src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts @@ -7,7 +7,7 @@ import SCREEN_TO_HISTORY_PARAM from '@src/libs/Navigation/linkingConfig/RELATION import type {Screen} from '@src/SCREENS'; import type {HistoryStackNavigatorAction, SetHistoryParamActionType} from './types'; -const CUSTOM_HISTORY_PREFIX = 'CUSTOM_HISTORY_'; +const CUSTOM_HISTORY_PREFIX = 'CUSTOM_HISTORY'; function isSetParamsAction(action: HistoryStackNavigatorAction): action is SetParamsAction { return action.type === CONST.NAVIGATION.ACTION_TYPE.SET_PARAMS; From b569d95fb812fd1d9d3382d0d874835a8e4f4cb2 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 21 May 2025 15:03:09 +0200 Subject: [PATCH 3/4] remove redundant getCustomHistoryEntry --- .../addCustomHistoryRouterExtension.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts b/src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts index 0b16e42c8e51e..ca2deafc7493c 100644 --- a/src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts +++ b/src/libs/Navigation/AppNavigator/customHistory/addCustomHistoryRouterExtension.ts @@ -35,7 +35,7 @@ function getCustomHistoryEntry(routeName: string) { function addCustomHistoryRouterExtension( originalRouter: PlatformStackRouterFactory, ) { - return (options: RouterOptions): Router, CommonActions.Action | StackActionType | HistoryStackNavigatorAction> => { + return (options: RouterOptions): Router, HistoryStackNavigatorAction> => { const router = originalRouter(options); const enhanceStateWithHistory = (state: PlatformStackNavigationState) => { @@ -55,13 +55,17 @@ function addCustomHistoryRouterExtension)[customHistoryParamName] && // The last history entry should not be the custom history entry for the focused route to avoid duplication - stateWithInitialHistory.history.at(-1) !== getCustomHistoryEntry(focusedRoute.name) + stateWithInitialHistory.history.at(-1) !== customHistoryEntry ) { // Add the custom history entry to the initial history - stateWithInitialHistory.history = [...stateWithInitialHistory.history, getCustomHistoryEntry(focusedRoute.name)]; + stateWithInitialHistory.history = [...stateWithInitialHistory.history, customHistoryEntry]; } return stateWithInitialHistory; @@ -90,6 +94,8 @@ function addCustomHistoryRouterExtension { // We want to set the right param and then update the history if (isSetHistoryParamAction(action)) { + const customHistoryEntry = getCustomHistoryEntry(action.payload.key); + // Start with updating the param. const setParamsAction = CommonActions.setParams({[action.payload.key]: action.payload.value}); const stateWithUpdatedParams = router.getStateForAction(state, setParamsAction, configOptions); @@ -100,13 +106,13 @@ function addCustomHistoryRouterExtension entry !== getCustomHistoryEntry(action.payload.key))}; + return {...stateWithUpdatedParams, history: stateWithUpdatedParams.history.filter((entry) => entry !== customHistoryEntry)}; } // Else, do not change history. From f072475a8d7979c838743f03645411ffdbde889e Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Thu, 22 May 2025 15:52:40 +0200 Subject: [PATCH 4/4] fix useCustomHistoryParam for native platforms --- .../createPlatformStackNavigatorComponent/index.native.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.native.tsx b/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.native.tsx index 1f3b4a4c04cea..f2b6fcf7eb320 100644 --- a/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.native.tsx +++ b/src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.native.tsx @@ -3,6 +3,7 @@ import {StackRouter, useNavigationBuilder} from '@react-navigation/native'; import {NativeStackView} from '@react-navigation/native-stack'; import type {NativeStackNavigationEventMap, NativeStackNavigationOptions} from '@react-navigation/native-stack'; import React, {useMemo} from 'react'; +import {addCustomHistoryRouterExtension} from '@libs/Navigation/AppNavigator/customHistory'; import convertToNativeNavigationOptions from '@libs/Navigation/PlatformStackNavigation/navigationOptions/convertToNativeNavigationOptions'; import type { CreatePlatformStackNavigatorComponentOptions, @@ -18,7 +19,7 @@ function createPlatformStackNavigatorComponent, ) { - const createRouter = options?.createRouter ?? StackRouter; + const createRouter = addCustomHistoryRouterExtension(options?.createRouter ?? StackRouter); const defaultScreenOptions = options?.defaultScreenOptions; const useCustomState = options?.useCustomState ?? (() => undefined); const useCustomEffects = options?.useCustomEffects ?? (() => undefined);