When we try to develop complex designs for our components we end up sacrificing how they work in the Experience Editor or Pages Editor. A common example is creating styled links which can get pretty tricky. After some investigating and experimenting I found a cool way to handle these challenges and make it so future solutions can utilize this method.
In order to use the Sitecore Context we’ll have to import useSitecoreContext
from `@sitecore-jss/sitecore-jss-nextjs
like the code below.
import { useSitecoreContext } from '@sitecore-jss/sitecore-jss-nextjs';
Inside your component, with useSitecoreContext
you can then access sitecoreContext
which contains useful values which will help you through switching between components depending on what view you’re on.
const { sitecoreContext } = useSitecoreContext();
The sitecoreContext
contains two useful properties,
pageEditing
- a Boolean value which indicates if you are inside an Editor.pageState
- a string value which can be either normal
, preview
or edit
.By using the sitecoreContext.pageEditing
we can either manipulate the component rendered or manipulate the data used by the component.
A good example for this is when we are handling links managed externally. These links may not be using the JSS Link component or they are a part of the Partial Designs which makes them static. The problem lies when an editor accidentally clicks on them hoping to edit them or was a bit too curious. They end up getting the consequence of being redirected to a bad URL. The code below is a good example of an Link that only shows an Icon. We would prefer only showing a div tag when editing instead of the Link.
if (sitecoreContext.pageEditing) {
return (
<div>
<Icon />
</div>
);
} else {
return (
<Link href={url}>
<Icon />
</Link>
);
}
Another good challenge is when we need dynamic content on a part of your component. As you can see on the image below we have the content with a dynamic piece {date}
which should be calculated in code.
We can switch between code relying if the page is in Edit Mode or not. We can use the JSS Components to allow them to be editable while showing the dynamic one outside of the Editor.
import React from 'react';
import { RichText, useSitecoreContext, RichTextField } from '@sitecore-jss/sitecore-jss-nextjs';
export type DateTodayProps = {
fields: {
body: RichTextField;
};
date: string; // A VALUE PASSED USING getStaticProps
};
export const Default = ({ fields, date }: DateTodayProps) => {
const { sitecoreContext } = useSitecoreContext();
const renderBody = () => {
const notificationText = fields?.body?.value ?? '';
return notificationText.replace('{date}', `<strong>${date}</strong>`);
};
return (
<div>
{sitecoreContext.pageEditing ? (
<RichText field={fields.successBody} />
) : (
<div dangerouslySetInnerHTML={{ __html: renderBody() }} />
)}
</div>
);
};
If you have certain conditions as well where your component doesn’t work well in Preview Mode then we can use pageState
instead. Check out the revised code below.
return (
<div>
{sitecoreContext.pageState != ('normal' as LayoutServicePageState) ? (
<RichText field={fields.successBody} />
) : (
<div dangerouslySetInnerHTML={{ __html: renderBody() }} />
)}
</div>
);
When pageState
has the value normal
it means that it’s being rendered outside of the Editors as well as not on Preview Mode.
To keep it simple, it all depends on the requirements of your components. I have introduced to you a way to help improve how you handle data and manipulate it in order to achieve your goal when published while still maintaining editability.