Skip to content
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

fix: App freeze when clearing cache #51725

Merged
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
42 changes: 25 additions & 17 deletions src/components/OptionListContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -17,14 +16,11 @@ type OptionsListContextProps = {
initializeOptions: () => void;
/** Flag to check if the options are initialized */
areOptionsInitialized: boolean;
/** Function to reset the options */
resetOptions: () => void;
};

type OptionsListProviderOnyxProps = {
/** Collection of reports */
reports: OnyxCollection<Report>;
};

type OptionsListProviderProps = OptionsListProviderOnyxProps & {
type OptionsListProviderProps = {
/** Actual content wrapped by this component */
children: React.ReactNode;
};
Expand All @@ -36,6 +32,7 @@ const OptionsListContext = createContext<OptionsListContextProps>({
},
initializeOptions: () => {},
areOptionsInitialized: false,
resetOptions: () => {},
});

const isEqualPersonalDetail = (prevPersonalDetail: PersonalDetails | null, personalDetail: PersonalDetails | null) =>
Expand All @@ -44,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<OptionList>({
reports: [],
personalDetails: [],
});
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);

const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT;
const prevPersonalDetails = usePrevious(personalDetails);
Expand Down Expand Up @@ -144,9 +142,22 @@ function OptionsListContextProvider({reports, children}: OptionsListProviderProp
areOptionsInitialized.current = true;
}, [loadOptions]);

const resetOptions = useCallback(() => {
if (!areOptionsInitialized.current) {
return;
}

areOptionsInitialized.current = false;
setOptions({
reports: [],
personalDetails: [],
});
}, []);

return (
// eslint-disable-next-line react-compiler/react-compiler
<OptionsListContext.Provider value={useMemo(() => ({options, initializeOptions, areOptionsInitialized: areOptionsInitialized.current}), [options, initializeOptions])}>
<OptionsListContext.Provider // eslint-disable-next-line react-compiler/react-compiler
value={useMemo(() => ({options, initializeOptions, areOptionsInitialized: areOptionsInitialized.current, resetOptions}), [options, initializeOptions, resetOptions])}
>
{children}
</OptionsListContext.Provider>
);
Expand All @@ -157,7 +168,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) {
Expand All @@ -171,13 +182,10 @@ const useOptionsList = (options?: {shouldInitialize: boolean}) => {
initializeOptions,
options: optionsList,
areOptionsInitialized,
resetOptions,
};
};

export default withOnyx<OptionsListProviderProps, OptionsListProviderOnyxProps>({
reports: {
key: ONYXKEYS.COLLECTION.REPORT,
},
})(OptionsListContextProvider);
export default OptionsListContextProvider;

export {useOptionsListContext, useOptionsList, OptionsListContext};
3 changes: 3 additions & 0 deletions src/pages/settings/Troubleshoot/TroubleshootPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<string, unknown>) => {
Expand Down Expand Up @@ -160,6 +162,7 @@ function TroubleshootPage() {
isVisible={isConfirmationModalVisible}
onConfirm={() => {
setIsConfirmationModalVisible(false);
resetOptions();
clearOnyxAndResetApp();
}}
onCancel={() => setIsConfirmationModalVisible(false)}
Expand Down
2 changes: 1 addition & 1 deletion tests/perf-test/SearchRouter.perf-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ function SearchRouterInputWrapper() {
function SearchRouterWrapperWithCachedOptions() {
return (
<ComposeProviders components={[OnyxProvider, LocaleContextProvider]}>
<OptionsListContext.Provider value={useMemo(() => ({options: mockedOptions, initializeOptions: () => {}, areOptionsInitialized: true}), [])}>
<OptionsListContext.Provider value={useMemo(() => ({options: mockedOptions, initializeOptions: () => {}, resetOptions: () => {}, areOptionsInitialized: true}), [])}>
<SearchRouter onRouterClose={mockOnClose} />
</OptionsListContext.Provider>
</ComposeProviders>
Expand Down
Loading