diff --git a/CHANGELOG.md b/CHANGELOG.md index dc90dc805..acf5a4e03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Not released +- cache Intl instances to improve performance [#894](https://github.com/CartoDB/carto-react/pull/894) - Support for `onRowMouseEnter` and `onRowMouseLeave` handlers for Table Widget [#907](https://github.com/CartoDB/carto-react/pull/907) ## 3.0.0 diff --git a/packages/react-ui/src/hooks/useImperativeIntl.js b/packages/react-ui/src/hooks/useImperativeIntl.js index 3179669f0..73bf686af 100644 --- a/packages/react-ui/src/hooks/useImperativeIntl.js +++ b/packages/react-ui/src/hooks/useImperativeIntl.js @@ -8,22 +8,40 @@ import { } from '../localization/localeUtils'; const cache = createIntlCache(); +const intlInstanceCache = new WeakMap(); -export default function useImperativeIntl(intlConfig) { - return useMemo(() => { - const locale = intlConfig?.locale || DEFAULT_LOCALE; - const messagesLocale = findMatchingMessagesLocale(locale, messages); - const intMessages = { - ...(messages[messagesLocale] || {}), - ...(intlConfig?.messages || {}) - }; +const createIntlInstance = (intlConfig) => { + const locale = intlConfig?.locale || DEFAULT_LOCALE; + const messagesLocale = findMatchingMessagesLocale(locale, messages); + const intMessages = { + ...(messages[messagesLocale] || {}), + ...(intlConfig?.messages || {}) + }; + + const combinedMessages = flattenMessages(intMessages); + return createIntl( + { + locale, + messages: combinedMessages + }, + cache + ); +}; - return createIntl( - { - locale, - messages: flattenMessages(intMessages) - }, - cache - ); - }, [intlConfig]); +const getGloballyCachedIntl = (intlConfig) => { + // This is very simple cache exploits fact that Intl instance is actually same for most of time + // so we can reuse those maps across several instances of same components + // note, useMemo can't cache accross many that globally and flattenMessages over _app_ and c4r messages is quite costly + // and would be paid for every c4r component mounted. + let cachedInstance = intlInstanceCache.get(intlConfig); + if (cachedInstance) { + return cachedInstance; + } + const newInstance = createIntlInstance(intlConfig); + intlInstanceCache.set(intlConfig, newInstance); + return newInstance; +}; + +export default function useImperativeIntl(intlConfig) { + return getGloballyCachedIntl(intlConfig); }