From 0b9e80ebb99bdffe01c80ac41042d27ae33e88d6 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Wed, 30 Oct 2024 11:24:04 +0100 Subject: [PATCH 1/3] fix app freeze when clearing cache --- src/components/OptionListContextProvider.tsx | 22 +++++++++++++++++-- .../Troubleshoot/TroubleshootPage.tsx | 3 +++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/components/OptionListContextProvider.tsx b/src/components/OptionListContextProvider.tsx index f098188de270..c0985a482dec 100644 --- a/src/components/OptionListContextProvider.tsx +++ b/src/components/OptionListContextProvider.tsx @@ -17,6 +17,8 @@ type OptionsListContextProps = { initializeOptions: () => void; /** Flag to check if the options are initialized */ areOptionsInitialized: boolean; + /** Function to reset the options */ + resetOptions: () => void; }; type OptionsListProviderOnyxProps = { @@ -36,6 +38,7 @@ const OptionsListContext = createContext({ }, initializeOptions: () => {}, areOptionsInitialized: false, + resetOptions: () => {}, }); const isEqualPersonalDetail = (prevPersonalDetail: PersonalDetails | null, personalDetail: PersonalDetails | null) => @@ -144,8 +147,22 @@ function OptionsListContextProvider({reports, children}: OptionsListProviderProp areOptionsInitialized.current = true; }, [loadOptions]); + const resetOptions = useCallback(() => { + if (!areOptionsInitialized.current) { + return; + } + + areOptionsInitialized.current = false; + setOptions({ + reports: [], + personalDetails: [], + }); + }, []); + return ( - ({options, initializeOptions, areOptionsInitialized: areOptionsInitialized.current}), [options, initializeOptions])}> + ({options, initializeOptions, areOptionsInitialized: areOptionsInitialized.current, resetOptions}), [options, initializeOptions, resetOptions])} + > {children} ); @@ -156,7 +173,7 @@ const useOptionsListContext = () => useContext(OptionsListContext); // Hook to use the OptionsListContext with an initializer to load the options const useOptionsList = (options?: {shouldInitialize: boolean}) => { const {shouldInitialize = true} = options ?? {}; - const {initializeOptions, options: optionsList, areOptionsInitialized} = useOptionsListContext(); + const {initializeOptions, options: optionsList, areOptionsInitialized, resetOptions} = useOptionsListContext(); useEffect(() => { if (!shouldInitialize || areOptionsInitialized) { @@ -170,6 +187,7 @@ const useOptionsList = (options?: {shouldInitialize: boolean}) => { initializeOptions, options: optionsList, areOptionsInitialized, + resetOptions, }; }; diff --git a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx index 69293fe894d4..bd0ce596c733 100644 --- a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx +++ b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx @@ -11,6 +11,7 @@ import * as Illustrations from '@components/Icon/Illustrations'; import ImportOnyxState from '@components/ImportOnyxState'; import LottieAnimations from '@components/LottieAnimations'; import MenuItemList from '@components/MenuItemList'; +import {useOptionsList} from '@components/OptionListContextProvider'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; import Section from '@components/Section'; @@ -51,6 +52,7 @@ function TroubleshootPage() { const [isLoading, setIsLoading] = useState(false); const [shouldStoreLogs] = useOnyx(ONYXKEYS.SHOULD_STORE_LOGS); const [shouldMaskOnyxState = true] = useOnyx(ONYXKEYS.SHOULD_MASK_ONYX_STATE); + const {resetOptions} = useOptionsList({shouldInitialize: false}); const exportOnyxState = useCallback(() => { ExportOnyxState.readFromOnyxDatabase().then((value: Record) => { @@ -160,6 +162,7 @@ function TroubleshootPage() { isVisible={isConfirmationModalVisible} onConfirm={() => { setIsConfirmationModalVisible(false); + resetOptions(); clearOnyxAndResetApp(); }} onCancel={() => setIsConfirmationModalVisible(false)} From f8ef43abb375ba63cea4e7b2b18dd8459ee11db0 Mon Sep 17 00:00:00 2001 From: MrRefactor Date: Sun, 3 Nov 2024 20:48:30 +0100 Subject: [PATCH 2/3] Fix failing checks --- src/components/OptionListContextProvider.tsx | 3 +-- tests/perf-test/SearchRouter.perf-test.tsx | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/OptionListContextProvider.tsx b/src/components/OptionListContextProvider.tsx index ae8048f5454c..e57246315053 100644 --- a/src/components/OptionListContextProvider.tsx +++ b/src/components/OptionListContextProvider.tsx @@ -160,8 +160,7 @@ function OptionsListContextProvider({reports, children}: OptionsListProviderProp }, []); return ( - // eslint-disable-next-line react-compiler/react-compiler - ({options, initializeOptions, areOptionsInitialized: areOptionsInitialized.current, resetOptions}), [options, initializeOptions, resetOptions])} > {children} diff --git a/tests/perf-test/SearchRouter.perf-test.tsx b/tests/perf-test/SearchRouter.perf-test.tsx index e5a0b2e30533..cf774222a807 100644 --- a/tests/perf-test/SearchRouter.perf-test.tsx +++ b/tests/perf-test/SearchRouter.perf-test.tsx @@ -141,7 +141,7 @@ function SearchRouterInputWrapper() { function SearchRouterWrapperWithCachedOptions() { return ( - ({options: mockedOptions, initializeOptions: () => {}, areOptionsInitialized: true}), [])}> + ({options: mockedOptions, initializeOptions: () => {}, resetOptions: () => {}, areOptionsInitialized: true}), [])}> From f326c30e11407af26f664ad0627061f5e2d63a38 Mon Sep 17 00:00:00 2001 From: MrRefactor Date: Sun, 3 Nov 2024 21:02:56 +0100 Subject: [PATCH 3/3] Refactor OptionsListContextProvider into useOnyx --- src/components/OptionListContextProvider.tsx | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/components/OptionListContextProvider.tsx b/src/components/OptionListContextProvider.tsx index e57246315053..b14a26138b6e 100644 --- a/src/components/OptionListContextProvider.tsx +++ b/src/components/OptionListContextProvider.tsx @@ -1,6 +1,5 @@ import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react'; -import {withOnyx} from 'react-native-onyx'; -import type {OnyxCollection} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import usePrevious from '@hooks/usePrevious'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import type {OptionList} from '@libs/OptionsListUtils'; @@ -21,12 +20,7 @@ type OptionsListContextProps = { resetOptions: () => void; }; -type OptionsListProviderOnyxProps = { - /** Collection of reports */ - reports: OnyxCollection; -}; - -type OptionsListProviderProps = OptionsListProviderOnyxProps & { +type OptionsListProviderProps = { /** Actual content wrapped by this component */ children: React.ReactNode; }; @@ -47,12 +41,13 @@ const isEqualPersonalDetail = (prevPersonalDetail: PersonalDetails | null, perso prevPersonalDetail?.login === personalDetail?.login && prevPersonalDetail?.displayName === personalDetail?.displayName; -function OptionsListContextProvider({reports, children}: OptionsListProviderProps) { +function OptionsListContextProvider({children}: OptionsListProviderProps) { const areOptionsInitialized = useRef(false); const [options, setOptions] = useState({ reports: [], personalDetails: [], }); + const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT; const prevPersonalDetails = usePrevious(personalDetails); @@ -191,10 +186,6 @@ const useOptionsList = (options?: {shouldInitialize: boolean}) => { }; }; -export default withOnyx({ - reports: { - key: ONYXKEYS.COLLECTION.REPORT, - }, -})(OptionsListContextProvider); +export default OptionsListContextProvider; export {useOptionsListContext, useOptionsList, OptionsListContext};