Skip to content

Commit e0e2d2e

Browse files
authored
Merge pull request #88097 from callstack-internal/perf/defer-styles-computation-lazy-proxy-v2
[No QA] perf: defer styles computation from module import to provider render
2 parents f855ba5 + 1536786 commit e0e2d2e

File tree

8 files changed

+49
-29
lines changed

8 files changed

+49
-29
lines changed
Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,34 @@
1-
// eslint-disable-next-line no-restricted-imports
2-
import {defaultStyles} from '@styles/index';
3-
// eslint-disable-next-line no-restricted-imports
4-
import {DefaultStyleUtils} from '@styles/utils';
1+
import styles from '@src/styles';
2+
import {defaultTheme} from '@src/styles/theme';
3+
import createStyleUtils from '@src/styles/utils';
54
import type {ThemeStylesActionsContextType, ThemeStylesStateContextType} from './types';
65

7-
const defaultThemeStylesStateContextValue: ThemeStylesStateContextType = {
8-
styles: defaultStyles,
9-
};
6+
// Lazy defaults: defers the expensive styles(defaultTheme) call from module import
7+
// time to first access. In production, ThemeStylesProvider supplies real values so
8+
// these are never reached. Tests that render without the provider will trigger lazy
9+
// initialization on first access.
10+
let cachedState: ThemeStylesStateContextType | undefined;
11+
let cachedActions: ThemeStylesActionsContextType | undefined;
1012

11-
const defaultThemeStylesActionsContextValue: ThemeStylesActionsContextType = {
12-
StyleUtils: DefaultStyleUtils,
13-
};
13+
const defaultThemeStylesStateContextValue = new Proxy({} as ThemeStylesStateContextType, {
14+
get(_, prop: keyof ThemeStylesStateContextType) {
15+
if (!cachedState) {
16+
cachedState = {styles: styles(defaultTheme)};
17+
}
18+
return cachedState[prop];
19+
},
20+
});
21+
22+
const defaultThemeStylesActionsContextValue = new Proxy({} as ThemeStylesActionsContextType, {
23+
get(_, prop: keyof ThemeStylesActionsContextType) {
24+
if (!cachedActions) {
25+
if (!cachedState) {
26+
cachedState = {styles: styles(defaultTheme)};
27+
}
28+
cachedActions = {StyleUtils: createStyleUtils(defaultTheme, cachedState.styles)};
29+
}
30+
return cachedActions[prop];
31+
},
32+
});
1433

1534
export {defaultThemeStylesStateContextValue, defaultThemeStylesActionsContextValue};

src/stories/CheckboxWithLabel.stories.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import React from 'react';
33
import CheckboxWithLabel from '@components/CheckboxWithLabel';
44
import type {CheckboxWithLabelProps} from '@components/CheckboxWithLabel';
55
import Text from '@components/Text';
6-
// eslint-disable-next-line no-restricted-imports
7-
import {defaultStyles} from '@styles/index';
6+
import styles from '@src/styles';
7+
import {defaultTheme} from '@src/styles/theme';
8+
9+
const defaultStyles = styles(defaultTheme);
810

911
type CheckboxWithLabelStory = StoryFn<typeof CheckboxWithLabel>;
1012

src/stories/Composer.stories.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import RenderHTML from '@components/RenderHTML';
99
import Text from '@components/Text';
1010
import withNavigationFallback from '@components/withNavigationFallback';
1111
import useStyleUtils from '@hooks/useStyleUtils';
12-
// eslint-disable-next-line no-restricted-imports
13-
import {defaultTheme} from '@styles/theme';
14-
import {defaultStyles} from '@src/styles';
12+
import styles from '@src/styles';
13+
import {defaultTheme} from '@src/styles/theme';
1514
import type {FileObject} from '@src/types/utils/Attachment';
1615

16+
const defaultStyles = styles(defaultTheme);
17+
1718
const ComposerWithNavigation = withNavigationFallback(Composer);
1819

1920
/**

src/stories/DragAndDrop.stories.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import {Image, View} from 'react-native';
44
import DragAndDropConsumer from '@components/DragAndDrop/Consumer';
55
import DragAndDropProvider from '@components/DragAndDrop/Provider';
66
import Text from '@components/Text';
7-
import {defaultStyles} from '@src/styles';
7+
import styles from '@src/styles';
8+
import {defaultTheme} from '@src/styles/theme';
9+
10+
const defaultStyles = styles(defaultTheme);
811

912
/**
1013
* We use the Component Story Format for writing stories. Follow the docs here:

src/stories/Form.stories.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ import {isRequiredFulfilled} from '@libs/ValidationUtils';
1717
import {clearErrors, setDraftValues, setErrors, setIsLoading} from '@userActions/FormActions';
1818
import CONST from '@src/CONST';
1919
import type {OnyxFormValuesMapping} from '@src/ONYXKEYS';
20-
import {defaultStyles} from '@src/styles';
20+
import styles from '@src/styles';
21+
import {defaultTheme} from '@src/styles/theme';
2122
import type {Form} from '@src/types/form';
2223

24+
const defaultStyles = styles(defaultTheme);
25+
2326
type FormStory = StoryFn<FormProviderProps & FormProviderOnyxProps>;
2427

2528
type StorybookFormValues = {

src/stories/NumberWithSymbolForm.stories.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import NumberWithSymbolForm from '@components/NumberWithSymbolForm';
55
import type {NumberWithSymbolFormProps} from '@components/NumberWithSymbolForm';
66
import ScrollView from '@components/ScrollView';
77
import withNavigationFallback from '@components/withNavigationFallback';
8-
// eslint-disable-next-line no-restricted-imports
9-
import {defaultStyles} from '@styles/index';
108
import CONST from '@src/CONST';
9+
import styles from '@src/styles';
10+
import {defaultTheme} from '@src/styles/theme';
11+
12+
const defaultStyles = styles(defaultTheme);
1113

1214
type NumberWithSymbolFormStory = StoryFn<typeof NumberWithSymbolForm>;
1315

src/styles/index.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import {getBrowser, isMobile, isMobileSafari, isSafari} from '@libs/Browser';
1919
import getPlatform from '@libs/getPlatform';
2020
import CONST from '@src/CONST';
2121
import type {Dimensions} from '@src/types/utils/Layout';
22-
import {defaultTheme} from './theme';
2322
import colors from './theme/colors';
2423
import type {ThemeColors} from './theme/types';
2524
import addOutlineWidth from './utils/addOutlineWidth';
@@ -6588,8 +6587,5 @@ const styles = (theme: ThemeColors) =>
65886587

65896588
type ThemeStyles = ReturnType<typeof styles>;
65906589

6591-
const defaultStyles = styles(defaultTheme);
6592-
65936590
export default styles;
6594-
export {defaultStyles};
65956591
export type {ThemeStyles, StatusBarStyle, ColorScheme, AnchorPosition, AnchorDimensions, OverlayStylesParams};

src/styles/utils/index.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,13 @@ import {LETTER_AVATAR_COLOR_OPTIONS} from '@libs/Avatars/PresetAvatarCatalog';
99
import {isMobile, isMobileChrome} from '@libs/Browser';
1010
import getPlatform from '@libs/getPlatform';
1111
import {hashText} from '@libs/UserUtils';
12-
// eslint-disable-next-line no-restricted-imports
13-
import {defaultTheme} from '@styles/theme';
1412
import colors from '@styles/theme/colors';
1513
import type {ThemeColors} from '@styles/theme/types';
1614
import variables from '@styles/variables';
1715
import CONST from '@src/CONST';
1816
import type {Transaction} from '@src/types/onyx';
1917
import type {Dimensions} from '@src/types/utils/Layout';
2018
import type Nullable from '@src/types/utils/Nullable';
21-
import {defaultStyles} from '..';
2219
import type {ThemeStyles} from '..';
2320
import shouldPreventScrollOnAutoCompleteSuggestion from './autoCompleteSuggestion';
2421
import getCardStyles from './cardStyles';
@@ -2291,8 +2288,5 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
22912288

22922289
type StyleUtilsType = ReturnType<typeof createStyleUtils>;
22932290

2294-
const DefaultStyleUtils = createStyleUtils(defaultTheme, defaultStyles);
2295-
22962291
export default createStyleUtils;
2297-
export {DefaultStyleUtils};
22982292
export type {StyleUtilsType, AvatarSizeName};

0 commit comments

Comments
 (0)