Skip to content

Commit

Permalink
[Nextjs] Dynamic components markup is missing in Experience Editor af…
Browse files Browse the repository at this point in the history
…ter adding new rendering (#1019)

* Adding an extra componentFactory method to work in editing mode

* addressing comments, prettifying code

* Update packages/create-sitecore-jss/src/templates/nextjs/scripts/templates/component-factory.ts

Co-authored-by: Illia Kovalenko <23364749+illiakovalenko@users.noreply.github.com>
  • Loading branch information
art-alexeyenko and illiakovalenko authored May 23, 2022
1 parent d3e2ea2 commit ba8cd0d
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ ${componentFiles
const moduleName = removeDynamicModuleNameEnding(component.moduleName);
return `const ${moduleName} = {
module: () => import('${component.path}'),
element: () => dynamic(${moduleName}.module)
element: (isEditing?: boolean) => isEditing ? require('${component.path}')?.default : dynamic(${moduleName}.module)
}`;
}
Expand Down Expand Up @@ -89,6 +89,10 @@ ${componentFiles
// componentFactory uses 'dynamic(...)' because primary usage of it to render 'React Component' (default export).
// See https://nextjs.org/docs/advanced-features/dynamic-import
// At the end you will have single preloaded script for each lazy loading module.
// Editing mode doesn't work well with dynamic components in nextjs: dynamic components are not displayed without refresh after a rendering is added.
// This happens beacuse Experience Editor simply inserts updated HTML generated on server side. This conflicts with nextjs dynamic logic as no HTML gets rendered for dynamic component
// So we use require() to obtain dynamic components in editing mode while preserving dynamic logic for non-editing scenarios
// As we need to be able to seamlessly work with dynamic components in both editing and normal modes, different componentFactory functions will be passed to app
export function componentModule(componentName: string) {
const component = components.get(componentName);
Expand All @@ -101,14 +105,14 @@ export function componentModule(componentName: string) {
return component;
}
export function componentFactory(componentName: string, exportName?: string) {
function baseComponentFactory(componentName: string, exportName?: string, isEditing: boolean) {
const component = components.get(componentName);
// check that component should be dynamically imported
if (component?.element) {
// return next.js dynamic import
return component.element();
return component.element(isEditing);
}
if (exportName) {
Expand All @@ -117,6 +121,14 @@ export function componentFactory(componentName: string, exportName?: string) {
return component?.default || component;
}
export function componentFactory(componentName: string, exportName?: string) {
return baseComponentFactory(componentName, exportName, false);
}
export function editingComponentFactory(componentName: string, exportName?: string) {
return baseComponentFactory(componentName, exportName, true);
}
`;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
} from '@sitecore-jss/sitecore-jss-nextjs';
import { SitecorePageProps } from 'lib/page-props';
import { sitecorePagePropsFactory } from 'lib/page-props-factory';
import { componentFactory } from 'temp/componentFactory';
// different componentFactory method will be used based on whether page is being edited
import { componentFactory, editingComponentFactory } from 'temp/componentFactory';
<% if (prerender === 'SSG') { -%>
import { sitemapFetcher } from 'lib/sitemap-fetcher';
<% } -%>
Expand All @@ -29,9 +30,14 @@ const SitecorePage = ({ notFound, componentProps, layoutData }: SitecorePageProp
return <NotFound />;
}

const isEditing = layoutData.sitecore.context.pageEditing;

return (
<ComponentPropsContext value={componentProps}>
<SitecoreContext componentFactory={componentFactory} layoutData={layoutData}>
<SitecoreContext
componentFactory={isEditing ? editingComponentFactory : componentFactory}
layoutData={layoutData}
>
<Layout layoutData={layoutData} />
</SitecoreContext>
</ComponentPropsContext>
Expand Down

0 comments on commit ba8cd0d

Please sign in to comment.