diff --git a/packages/samples/headless-ssr-commerce/app/products/[productId]/page.tsx b/packages/samples/headless-ssr-commerce/app/products/[productId]/page.tsx index e968419c120..2208ae33475 100644 --- a/packages/samples/headless-ssr-commerce/app/products/[productId]/page.tsx +++ b/packages/samples/headless-ssr-commerce/app/products/[productId]/page.tsx @@ -1,6 +1,8 @@ import * as externalCartAPI from '@/actions/external-cart-api'; import ContextDropdown from '@/components/context-dropdown'; import ProductPage from '@/components/pages/product-page'; +import StandaloneProvider from '@/components/providers/standalone-provider'; +import StandaloneSearchBox from '@/components/standalone-search-box'; import {searchEngineDefinition} from '@/lib/commerce-engine'; import {NextJsNavigatorContext} from '@/lib/navigatorContextProvider'; import {defaultContext} from '@/utils/context'; @@ -34,9 +36,13 @@ export default async function ProductDescriptionPage({ }, }); return ( - <> +

Product description page

+ Loading...

}>
- +
); } diff --git a/packages/samples/headless-ssr-commerce/components/providers/standalone-provider.tsx b/packages/samples/headless-ssr-commerce/components/providers/standalone-provider.tsx new file mode 100644 index 00000000000..a32a78d16ed --- /dev/null +++ b/packages/samples/headless-ssr-commerce/components/providers/standalone-provider.tsx @@ -0,0 +1,72 @@ +'use client'; + +import { + StandaloneHydratedState, + StandaloneStaticState, + standaloneEngineDefinition, +} from '@/lib/commerce-engine'; +import {NavigatorContext} from '@coveo/headless-react/ssr-commerce'; +import {PropsWithChildren, useEffect, useState} from 'react'; + +interface StandalonePageProps { + staticState: StandaloneStaticState; + navigatorContext: NavigatorContext; +} + +export default function StandaloneProvider({ + staticState, + navigatorContext, + children, +}: PropsWithChildren) { + const [hydratedState, setHydratedState] = useState< + StandaloneHydratedState | undefined + >(undefined); + + // Setting the navigator context provider also in client-side before hydrating the application + standaloneEngineDefinition.setNavigatorContextProvider( + () => navigatorContext + ); + + useEffect(() => { + standaloneEngineDefinition + .hydrateStaticState({ + searchAction: staticState.searchAction, + controllers: { + cart: { + initialState: {items: staticState.controllers.cart.state.items}, + }, + context: staticState.controllers.context.state, + }, + }) + .then(({engine, controllers}) => { + setHydratedState({engine, controllers}); + + // Refreshing recommendations in the browser after hydrating the state in the client-side + // Recommendation refresh in the server is not supported yet. + // controllers.popularBoughtRecs.refresh(); + }); + }, [staticState]); + + if (hydratedState) { + return ( + + {/* // TODO: KIT-3701: Type 'React.ReactNode' is not assignable to type 'import(".../node_modules/@types/react/index").ReactNode'. + Type 'bigint' is not assignable to type 'ReactNode'.*/} + <>{children} + + ); + } else { + return ( + + {/* // TODO: KIT-3701: Type 'React.ReactNode' is not assignable to type 'import(".../node_modules/@types/react/index").ReactNode'. + Type 'bigint' is not assignable to type 'ReactNode'.*/} + <>{children} + + ); + } +}