diff --git a/packages/pwa-kit-react-sdk/src/ssr/universal/components/route-component/index.js b/packages/pwa-kit-react-sdk/src/ssr/universal/components/route-component/index.js index b34ebc0c2a..069268f75b 100644 --- a/packages/pwa-kit-react-sdk/src/ssr/universal/components/route-component/index.js +++ b/packages/pwa-kit-react-sdk/src/ssr/universal/components/route-component/index.js @@ -56,11 +56,12 @@ const withErrorHandling = (Wrapped) => { */ export const routeComponent = (Wrapped, isPage, locals) => { const AppConfig = getAppConfig() - const extraArgs = AppConfig.extraGetPropsArgs(locals) const hocs = AppConfig.getHOCsInUse() const getPropsEnabled = hocs.indexOf(withLegacyGetProps) >= 0 + const extraArgs = getPropsEnabled ? AppConfig.extraGetPropsArgs(locals) : {} + /* istanbul ignore next */ const wrappedComponentName = Wrapped.displayName || Wrapped.name diff --git a/packages/template-retail-react-app/app/components/_app-config/index.jsx b/packages/template-retail-react-app/app/components/_app-config/index.jsx index e691ad4320..b464369b92 100644 --- a/packages/template-retail-react-app/app/components/_app-config/index.jsx +++ b/packages/template-retail-react-app/app/components/_app-config/index.jsx @@ -18,7 +18,6 @@ import {getConfig} from 'pwa-kit-runtime/utils/ssr-config' import {createUrlTemplate} from '../../utils/url' import {CommerceApiProvider} from 'commerce-sdk-react-preview' -import {withLegacyGetProps} from 'pwa-kit-react-sdk/ssr/universal/components/with-legacy-get-props' import {withReactQuery} from 'pwa-kit-react-sdk/ssr/universal/components/with-react-query' import {useCorrelationId} from 'pwa-kit-react-sdk/ssr/universal/hooks' import {getAppOrigin} from 'pwa-kit-react-sdk/utils/url' @@ -86,14 +85,6 @@ AppConfig.restore = (locals = {}) => { AppConfig.freeze = () => undefined -AppConfig.extraGetPropsArgs = (locals = {}) => { - return { - buildUrl: locals.buildUrl, - site: locals.site, - locale: locals.locale - } -} - AppConfig.propTypes = { children: PropTypes.node, locals: PropTypes.object @@ -119,4 +110,4 @@ const options = { } } -export default withReactQuery(withLegacyGetProps(AppConfig), options) +export default withReactQuery(AppConfig, options) diff --git a/packages/template-retail-react-app/app/components/_app/index.jsx b/packages/template-retail-react-app/app/components/_app/index.jsx index b86967fb5a..648b311148 100644 --- a/packages/template-retail-react-app/app/components/_app/index.jsx +++ b/packages/template-retail-react-app/app/components/_app/index.jsx @@ -11,7 +11,7 @@ import {useHistory, useLocation} from 'react-router-dom' import {getAssetUrl} from 'pwa-kit-react-sdk/ssr/universal/utils' import {getAppOrigin} from 'pwa-kit-react-sdk/utils/url' import {getConfig} from 'pwa-kit-runtime/utils/ssr-config' -import {useQueries} from '@tanstack/react-query' +import {useQuery, useQueries} from '@tanstack/react-query' import { useAccessToken, useCategory, @@ -62,7 +62,6 @@ import { } from '../../constants' import Seo from '../seo' -import {resolveLocaleFromUrl, resolveSiteFromUrl} from '../../utils/site-utils' const onClient = typeof window !== 'undefined' @@ -99,7 +98,7 @@ const useLazyLoadCategories = () => { } const App = (props) => { - const {children, targetLocale = DEFAULT_LOCALE, messages = {}} = props + const {children} = props const {data: categoriesTree} = useLazyLoadCategories() const categories = flatten(categoriesTree || {}, 'categories') @@ -116,6 +115,31 @@ const App = (props) => { const {isOpen, onOpen, onClose} = useDisclosure() + const targetLocale = getTargetLocale({ + getUserPreferredLocales: () => { + // CONFIG: This function should return an array of preferred locales. They can be + // derived from various sources. Below are some examples of those: + // + // - client side: window.navigator.languages + // - the page URL they're on (example.com/en-GB/home) + // - cookie (if their previous preference is saved there) + // + // If this function returns an empty array (e.g. there isn't locale in the page url), + // then the app would use the default locale as the fallback. + + // NOTE: Your implementation may differ, this is just what we did. + return [locale?.id || DEFAULT_LOCALE] + }, + l10nConfig: site.l10n + }) + + // Fetch the translation message data using the target locale. + const {data: messages} = useQuery({ + queryKey: ['app', 'translationas', 'messages', targetLocale], + queryFn: () => fetchTranslations(targetLocale), + enabled: isServer + }) + // Used to conditionally render header/footer for checkout page const isCheckout = /\/checkout$/.test(location?.pathname) @@ -201,6 +225,11 @@ const App = (props) => { { + if (!messages) { + // During the ssr prepass phase the messages object has not loaded, so we can suppress + // errors during this time. + return + } if (err.code === 'MISSING_TRANSLATION') { // NOTE: Remove the console error for missing translations during development, // as we knew translations would be added later. @@ -314,44 +343,8 @@ const App = (props) => { ) } -App.shouldGetProps = () => { - // In this case, we only want to fetch data for the app once, on the server. - return typeof window === 'undefined' -} - -App.getProps = async ({res}) => { - const site = resolveSiteFromUrl(res.locals.originalUrl) - const locale = resolveLocaleFromUrl(res.locals.originalUrl) - const l10nConfig = site.l10n - const targetLocale = getTargetLocale({ - getUserPreferredLocales: () => { - // CONFIG: This function should return an array of preferred locales. They can be - // derived from various sources. Below are some examples of those: - // - // - client side: window.navigator.languages - // - the page URL they're on (example.com/en-GB/home) - // - cookie (if their previous preference is saved there) - // - // If this function returns an empty array (e.g. there isn't locale in the page url), - // then the app would use the default locale as the fallback. - - // NOTE: Your implementation may differ, this is just what we did. - return [locale?.id] - }, - l10nConfig - }) - const messages = await fetchTranslations(targetLocale) - - return { - targetLocale, - messages - } -} - App.propTypes = { - children: PropTypes.node, - targetLocale: PropTypes.string, - messages: PropTypes.object + children: PropTypes.node } /** diff --git a/packages/template-retail-react-app/app/components/_app/index.test.js b/packages/template-retail-react-app/app/components/_app/index.test.js index 5822f5864e..09efdec83f 100644 --- a/packages/template-retail-react-app/app/components/_app/index.test.js +++ b/packages/template-retail-react-app/app/components/_app/index.test.js @@ -65,19 +65,6 @@ describe('App', () => { expect(screen.getByText('Any children here')).toBeInTheDocument() }) - test('shouldGetProps returns true only server-side', () => { - windowSpy.mockImplementation(() => undefined) - - expect(App.shouldGetProps()).toBe(true) - - windowSpy.mockImplementation(() => ({ - location: { - origin: 'http://localhost:3000/' - } - })) - expect(App.shouldGetProps()).toBe(false) - }) - test('The localized hreflang links exist in the html head', () => { useMultiSite.mockImplementation(() => resultUseMultiSite) renderWithProviders( diff --git a/packages/template-retail-react-app/app/pages/page-not-found/index.jsx b/packages/template-retail-react-app/app/pages/page-not-found/index.jsx index 86f593f6dd..bcce64328d 100644 --- a/packages/template-retail-react-app/app/pages/page-not-found/index.jsx +++ b/packages/template-retail-react-app/app/pages/page-not-found/index.jsx @@ -9,6 +9,7 @@ import React from 'react' import {Box, Heading, Flex, Button, Stack, Text} from '@chakra-ui/react' import {Helmet} from 'react-helmet' import {useIntl} from 'react-intl' +import {useServerContext} from 'pwa-kit-react-sdk/ssr/universal/hooks' import {SearchIcon} from '../../components/icons' import {useHistory} from 'react-router-dom' import Link from '../../components/link' @@ -16,6 +17,12 @@ import Link from '../../components/link' const PageNotFound = () => { const intl = useIntl() const history = useHistory() + const {res} = useServerContext() + + if (res) { + res.status(404) + } + return ( { ) } -PageNotFound.getProps = async ({res}) => { - if (res) { - res.status(404) - } -} - export default PageNotFound diff --git a/packages/template-retail-react-app/app/utils/test-utils.js b/packages/template-retail-react-app/app/utils/test-utils.js index 447af1cd80..83d34b7933 100644 --- a/packages/template-retail-react-app/app/utils/test-utils.js +++ b/packages/template-retail-react-app/app/utils/test-utils.js @@ -16,7 +16,6 @@ import {AddToCartModalProvider} from '../hooks/use-add-to-cart-modal' import {ServerContext} from 'pwa-kit-react-sdk/ssr/universal/contexts' import {IntlProvider} from 'react-intl' import {CommerceApiProvider} from 'commerce-sdk-react-preview' -import {withLegacyGetProps} from 'pwa-kit-react-sdk/ssr/universal/components/with-legacy-get-props' import {withReactQuery} from 'pwa-kit-react-sdk/ssr/universal/components/with-react-query' import fallbackMessages from '../translations/compiled/en-GB.json' import mockConfig from '../../config/mocks/default' @@ -170,7 +169,7 @@ TestProviders.propTypes = { * @param {object} options */ export const renderWithProviders = (children, options) => { - const TestProvidersWithDataAPI = withReactQuery(withLegacyGetProps(TestProviders), { + const TestProvidersWithDataAPI = withReactQuery(TestProviders, { queryClientConfig: { defaultOptions: { queries: {