import React, { useEffect, useState } from 'react'; import { withSitecoreContext, dataApi, Placeholder } from '@sitecore-jss/sitecore-jss-react'; import { dataFetcher } from './dataFetcher'; import config from './temp/config'; const HybridPlaceholder = ({ name, rendering, sitecoreContext, }) => { const { route, pageEditing, } = sitecoreContext; const [isFetched, setIsFetched] = useState(false); // Used to fetch the placeholder data with specific parameters. const fetchPlaceholder = () => dataApi.fetchPlaceholderData( name, route?.itemId, { layoutServiceConfig: { host: config.sitecoreApiHost, }, querystringParams: { sc_lang: route?.itemLanguage, sc_apikey: config.sitecoreApiKey, isHybridPlaceholder: true, }, fetcher: dataFetcher, }, ); // Will add the isLoaded prop to all components. const addIsLoadedProp = (isLoaded, elements) => { if (Array.isArray(elements)) { elements.forEach(({ fields }) => { if (fields) { fields.isLoaded = isLoaded; } }); } }; // Only fetch the placeholder data when we navigate to a new page. // Since useEffect does not work server-side we don't need a client-side check. useEffect(() => { if (!pageEditing && rendering?.placeholders?.[name]) { setIsFetched(false); fetchPlaceholder() .then(result => { addIsLoadedProp(true, result.elements); // Override all components in the placeholder with the new data. // This data contains the heavy code. rendering.placeholders[name] = result.elements; setIsFetched(true); }).catch(error => { console.error(error); }); } }, [route?.itemId]); if (!pageEditing && !isFetched && rendering?.placeholders?.[name]) { addIsLoadedProp(false, rendering.placeholders[name]); } return ( // Render the first time without the heavy data. // Render a second time with all the data loaded. ); }; export default withSitecoreContext()(HybridPlaceholder);