Skip to content

Commit e5572e1

Browse files
committed
fix: split I18nProvider internally into two components
A component uses`useDefaultLocale` and another the locale value set in the Provider.
1 parent e2ec321 commit e5572e1

File tree

1 file changed

+45
-16
lines changed

1 file changed

+45
-16
lines changed

packages/@react-aria/i18n/src/context.tsx

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13+
import {getDefaultLocale, Locale, useDefaultLocale} from './useDefaultLocale';
1314
import {isRTL} from './utils';
14-
import {Locale, useDefaultLocale} from './useDefaultLocale';
1515
import React, {JSX, ReactNode, useContext} from 'react';
1616

1717
export interface I18nProviderProps {
@@ -23,36 +23,65 @@ export interface I18nProviderProps {
2323

2424
const I18nContext = React.createContext<Locale | null>(null);
2525

26+
interface I18nProviderWithLocaleProps extends I18nProviderProps {
27+
locale: string
28+
}
29+
2630
/**
27-
* Provides the locale for the application to all child components.
31+
* Internal component that handles the case when locale is provided.
2832
*/
29-
export function I18nProvider(props: I18nProviderProps): JSX.Element {
30-
let {locale, children} = props;
31-
let defaultLocale = useDefaultLocale();
33+
function I18nProviderWithLocale(props: I18nProviderWithLocaleProps): JSX.Element {
34+
let {locale, children} = props;
35+
let value: Locale = React.useMemo(() => ({
36+
locale,
37+
direction: isRTL(locale) ? 'rtl' : 'ltr'
38+
}), [locale]);
39+
40+
return (
41+
<I18nContext.Provider value={value}>
42+
{children}
43+
</I18nContext.Provider>
44+
);
45+
}
3246

33-
let value: Locale = React.useMemo(() => {
34-
if (!locale) {
35-
return defaultLocale;
36-
}
47+
interface I18nProviderWithDefaultLocaleProps {
48+
children: ReactNode
49+
}
3750

38-
return {
39-
locale,
40-
direction: isRTL(locale) ? 'rtl' : 'ltr'
41-
};
42-
}, [defaultLocale, locale]);
51+
/**
52+
* Internal component that handles the case when no locale is provided.
53+
*/
54+
function I18nProviderWithDefaultLocale(props: I18nProviderWithDefaultLocaleProps): JSX.Element {
55+
let {children} = props;
56+
let defaultLocale = useDefaultLocale();
4357

4458
return (
45-
<I18nContext.Provider value={value}>
59+
<I18nContext.Provider value={defaultLocale}>
4660
{children}
4761
</I18nContext.Provider>
4862
);
4963
}
5064

65+
/**
66+
* Provides the locale for the application to all child components.
67+
*/
68+
export function I18nProvider(props: I18nProviderProps): JSX.Element {
69+
let {locale, children} = props;
70+
71+
// Conditionally render different components to avoid calling useDefaultLocale.
72+
// This is necessary because useDefaultLocale triggers a re-render.
73+
if (locale) {
74+
return <I18nProviderWithLocale locale={locale} children={children} />;
75+
}
76+
77+
return <I18nProviderWithDefaultLocale children={children} />;
78+
}
79+
5180
/**
5281
* Returns the current locale and layout direction.
5382
*/
5483
export function useLocale(): Locale {
55-
let defaultLocale = useDefaultLocale();
84+
let defaultLocale = getDefaultLocale();
5685
let context = useContext(I18nContext);
5786
return context || defaultLocale;
5887
}

0 commit comments

Comments
 (0)