Skip to content

fix: abracadabra page #48899

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
"react-native": "0.75.2",
"react-native-android-location-enabler": "^2.0.1",
"react-native-blob-util": "0.19.4",
"react-native-bundle-splitter": "^3.0.1",
Copy link
Contributor

@aimane-chnaif aimane-chnaif Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should follow the New Library Process

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submitted an issue here: #49519

"react-native-collapsible": "^1.6.2",
"react-native-config": "1.5.0",
"react-native-dev-menu": "^4.1.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
diff --git a/node_modules/@react-navigation/core/lib/module/useNavigationBuilder.js b/node_modules/@react-navigation/core/lib/module/useNavigationBuilder.js
index 6fb49e0..1f7c859 100644
--- a/node_modules/@react-navigation/core/lib/module/useNavigationBuilder.js
+++ b/node_modules/@react-navigation/core/lib/module/useNavigationBuilder.js
@@ -114,6 +114,16 @@ const getRouteConfigsFromChildren = (children, groupKey, groupOptions) => {
return configs;
};

+const useFullyMountedRef = () => {
+ const isFullyMountedRef = React.useRef(false);
+
+ React.useEffect(() => {
+ isFullyMountedRef.current = true;
+ }, []);
+
+ return isFullyMountedRef;
+};
+
/**
* Hook for building navigators.
*
@@ -122,6 +132,7 @@ const getRouteConfigsFromChildren = (children, groupKey, groupOptions) => {
* @returns An object containing `state`, `navigation`, `descriptors` objects.
*/
export default function useNavigationBuilder(createRouter, options) {
+ const isFullyMountedRef = useFullyMountedRef();
const navigatorKey = useRegisterNavigator();
const route = React.useContext(NavigationRouteContext);
const {
@@ -298,10 +309,18 @@ export default function useNavigationBuilder(createRouter, options) {
setState(nextState);
}
return () => {
- // We need to clean up state for this navigator on unmount
- if (getCurrentState() !== undefined && getKey() === navigatorKey) {
- setCurrentState(undefined);
- stateCleanedUp.current = true;
+ const cleanup = () => {
+ // We need to clean up state for this navigator on unmount
+ if (getCurrentState() !== undefined && getKey() === navigatorKey) {
+ setCurrentState(undefined);
+ stateCleanedUp.current = true;
+ }
+ }
+
+ if (!isFullyMountedRef.current) {
+ cleanup();
+ } else {
+ setTimeout(cleanup, 0);
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ LogBox.ignoreLogs([

const fill = {flex: 1};

const StrictModeWrapper = CONFIG.USE_REACT_STRICT_MODE_IN_DEV ? React.StrictMode : ({children}: {children: React.ReactElement}) => children;
const StrictModeWrapper = CONFIG.USE_REACT_STRICT_MODE_IN_DEV ? React.StrictMode : React.Fragment;

function App({url}: AppProps) {
useDefaultDragAndDrop();
Expand Down
33 changes: 24 additions & 9 deletions src/libs/Navigation/AppNavigator/index.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
import React, {lazy, memo, Suspense} from 'react';
import lazyRetry from '@src/utils/lazyRetry';
import React, {lazy, memo, Suspense, useEffect, useState} from 'react';
import {preload, register} from 'react-native-bundle-splitter';
import lazyRetry, {retryImport} from '@src/utils/lazyRetry';

const AuthScreens = lazy(() => lazyRetry(() => import('./AuthScreens')));
const PublicScreens = lazy(() => lazyRetry(() => import('./PublicScreens')));

const AUTH_SCREENS = 'AuthScreens';
const AuthScreens = register({
name: AUTH_SCREENS,
loader: () => retryImport(() => import('./AuthScreens')),
});

type AppNavigatorProps = {
/** If we have an authToken this is true */
authenticated: boolean;
};

function AppNavigator({authenticated}: AppNavigatorProps) {
if (authenticated) {
const [canNavigateToProtectedRoutes, setNavigateToProtectedRoutes] = useState(false);

useEffect(() => {
// Preload Auth Screens in advance to be sure that navigator can be mounted synchronously
// to avoid problems described in https://github.com/Expensify/App/issues/44600
preload()
.component(AUTH_SCREENS)
.then(() => {
setNavigateToProtectedRoutes(true);
});
}, []);

if (authenticated && canNavigateToProtectedRoutes) {
// These are the protected screens and only accessible when an authToken is present
return (
<Suspense fallback={null}>
<AuthScreens />
</Suspense>
);
// Navigate to them only when route is preloaded
return <AuthScreens />;
}

return (
Expand Down
11 changes: 9 additions & 2 deletions src/utils/lazyRetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ type Import<T> = Promise<{default: T}>;
type ComponentImport<T> = () => Import<T>;

/**
* Common retry mechanism for importing components.
*
* Attempts to lazily import a React component with a retry mechanism on failure.
* If the initial import fails the function will refresh the page once and retry the import.
* If the import fails again after the refresh, the error is propagated.
*
* @param componentImport - A function that returns a promise resolving to a lazily imported React component.
* @returns A promise that resolves to the imported component or rejects with an error after a retry attempt.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const lazyRetry = function <T extends ComponentType<any>>(componentImport: ComponentImport<T>): Import<T> {
function retryImport<T>(componentImport: ComponentImport<T>): Import<T> {
return new Promise((resolve, reject) => {
// Retrieve the retry status from sessionStorage, defaulting to 'false' if not set
const hasRefreshed = JSON.parse(sessionStorage.getItem(CONST.SESSION_STORAGE_KEYS.RETRY_LAZY_REFRESHED) ?? 'false') as boolean;
Expand All @@ -37,6 +38,12 @@ const lazyRetry = function <T extends ComponentType<any>>(componentImport: Compo
}
});
});
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const lazyRetry = function <T extends ComponentType<any>>(componentImport: ComponentImport<T>): Import<T> {
return retryImport(componentImport);
};

export default lazyRetry;
export {retryImport};
Loading