From 1cb4eaaa58b06eb9c02ca47bde35f6b2a80d3f1c Mon Sep 17 00:00:00 2001 From: Kevin Brian Bader Date: Mon, 11 Mar 2024 22:54:18 +0200 Subject: [PATCH 1/4] Performance and heat issues on the 'Troubleshoot' option --- src/components/Lottie/index.tsx | 11 +++++++-- src/hooks/useAppState/index.native.ts | 33 +++++++++++++++++++++++++++ src/hooks/useAppState/index.ts | 4 ++++ 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/hooks/useAppState/index.native.ts create mode 100644 src/hooks/useAppState/index.ts diff --git a/src/components/Lottie/index.tsx b/src/components/Lottie/index.tsx index 5c672cf7cab6..98ab00773d49 100644 --- a/src/components/Lottie/index.tsx +++ b/src/components/Lottie/index.tsx @@ -1,9 +1,11 @@ +import {useIsFocused} from '@react-navigation/native'; import type {LottieViewProps} from 'lottie-react-native'; import LottieView from 'lottie-react-native'; import type {ForwardedRef} from 'react'; import React, {forwardRef} from 'react'; import {View} from 'react-native'; import type DotLottieAnimation from '@components/LottieAnimations/types'; +import useAppState from '@hooks/useAppState'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -15,12 +17,17 @@ function Lottie({source, webStyle, ...props}: Props, ref: ForwardedRef setIsError(false)}); const aspectRatioStyle = styles.aspectRatioLottie(source); - // If the image fails to load, we'll just render an empty view - if (isError) { + // If the image fails to load or app is in background state, we'll just render an empty view + // using the fallback in case of a Lottie error or (isFocused || isBackground) to prevent + // memory leaks, see issue: https://github.com/Expensify/App/issues/36645 + if (isError || !isFocused || appState.isBackground) { return ; } diff --git a/src/hooks/useAppState/index.native.ts b/src/hooks/useAppState/index.native.ts new file mode 100644 index 000000000000..69e983aa9a82 --- /dev/null +++ b/src/hooks/useAppState/index.native.ts @@ -0,0 +1,33 @@ +import React from 'react'; +import type {AppStateStatus} from 'react-native'; +import {AppState} from 'react-native'; + +type AppStateType = { + isForeground: boolean; + isInactive: boolean; + isBackground: boolean; +}; + +function useAppState() { + const [appState, setAppState] = React.useState({ + isForeground: AppState.currentState === 'active', + isInactive: AppState.currentState === 'inactive', + isBackground: AppState.currentState === 'background', + }); + + React.useEffect(() => { + function handleAppStateChange(nextAppState: AppStateStatus) { + setAppState({ + isForeground: nextAppState === 'active', + isInactive: nextAppState === 'inactive', + isBackground: nextAppState === 'background', + }); + } + const subscription = AppState.addEventListener('change', handleAppStateChange); + return () => subscription.remove(); + }, []); + + return appState; +} + +export default useAppState; diff --git a/src/hooks/useAppState/index.ts b/src/hooks/useAppState/index.ts new file mode 100644 index 000000000000..0cece988a66c --- /dev/null +++ b/src/hooks/useAppState/index.ts @@ -0,0 +1,4 @@ +export default function useAppState() { + // Since there's no AppState in web, we'll always return isForeground as true + return {isForeground: true, isInactive: false, isBackground: false}; +} From 365903d70b49f80d959c8c95095cc7b86bf4749c Mon Sep 17 00:00:00 2001 From: Kevin Brian Bader Date: Tue, 12 Mar 2024 16:43:20 +0200 Subject: [PATCH 2/4] removed isFocused --- src/components/Lottie/index.tsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/components/Lottie/index.tsx b/src/components/Lottie/index.tsx index 98ab00773d49..08e7613dc7a9 100644 --- a/src/components/Lottie/index.tsx +++ b/src/components/Lottie/index.tsx @@ -1,4 +1,3 @@ -import {useIsFocused} from '@react-navigation/native'; import type {LottieViewProps} from 'lottie-react-native'; import LottieView from 'lottie-react-native'; import type {ForwardedRef} from 'react'; @@ -14,20 +13,18 @@ type Props = { } & Omit; function Lottie({source, webStyle, ...props}: Props, ref: ForwardedRef) { + const appState = useAppState(); const styles = useThemeStyles(); const [isError, setIsError] = React.useState(false); - const appState = useAppState(); - const isFocused = useIsFocused(); - useNetwork({onReconnect: () => setIsError(false)}); const aspectRatioStyle = styles.aspectRatioLottie(source); // If the image fails to load or app is in background state, we'll just render an empty view - // using the fallback in case of a Lottie error or (isFocused || isBackground) to prevent - // memory leaks, see issue: https://github.com/Expensify/App/issues/36645 - if (isError || !isFocused || appState.isBackground) { + // using the fallback in case of a Lottie error or appState.isBackground to prevent + // memory leak, see issue: https://github.com/Expensify/App/issues/36645 + if (isError || appState.isBackground) { return ; } From f690971eaa605a31012d9103402e27e4366141a1 Mon Sep 17 00:00:00 2001 From: Kevin Brian Bader Date: Tue, 12 Mar 2024 22:23:24 +0200 Subject: [PATCH 3/4] added types.ts file --- src/hooks/useAppState/index.native.ts | 7 +------ src/hooks/useAppState/types.ts | 7 +++++++ 2 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 src/hooks/useAppState/types.ts diff --git a/src/hooks/useAppState/index.native.ts b/src/hooks/useAppState/index.native.ts index 69e983aa9a82..39c1dff65e7c 100644 --- a/src/hooks/useAppState/index.native.ts +++ b/src/hooks/useAppState/index.native.ts @@ -1,12 +1,7 @@ import React from 'react'; import type {AppStateStatus} from 'react-native'; import {AppState} from 'react-native'; - -type AppStateType = { - isForeground: boolean; - isInactive: boolean; - isBackground: boolean; -}; +import type AppStateType from './types'; function useAppState() { const [appState, setAppState] = React.useState({ diff --git a/src/hooks/useAppState/types.ts b/src/hooks/useAppState/types.ts new file mode 100644 index 000000000000..9093b89fc4dc --- /dev/null +++ b/src/hooks/useAppState/types.ts @@ -0,0 +1,7 @@ +type AppStateType = { + isForeground: boolean; + isInactive: boolean; + isBackground: boolean; +}; + +export default AppStateType; From c512812cc2f93dbdc4a02336c8f0191086aeb5bc Mon Sep 17 00:00:00 2001 From: Kevin Brian Bader Date: Tue, 12 Mar 2024 22:43:33 +0200 Subject: [PATCH 4/4] added return AppStateType to useAppState web implementation --- src/hooks/useAppState/index.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hooks/useAppState/index.ts b/src/hooks/useAppState/index.ts index 0cece988a66c..74d68535d1d1 100644 --- a/src/hooks/useAppState/index.ts +++ b/src/hooks/useAppState/index.ts @@ -1,4 +1,8 @@ -export default function useAppState() { +import type AppStateType from './types'; + +function useAppState(): AppStateType { // Since there's no AppState in web, we'll always return isForeground as true return {isForeground: true, isInactive: false, isBackground: false}; } + +export default useAppState;