I think everyone can agree that having cleaner code is better for everyone. Whether you're reviewing a pull request or going back and debugging some old code, having easy-to-understand code is crucial. In this article, I'm going to cover three simple and easy ways to improve your JSS XM Cloud code.
After reading, you will be able to keep track of which component is which directly on your QA, Stage, or Production server (improving your debugging efficiency), enhance your code's legibility, and more easily split some of those large custom Sitecore components into easier-to-understand blocks!
Visualize this: You've just finished developing a new XM Cloud website for a client! Congratulations! The client has authored their entire site using Experience Editor or Sitecore Pages, and you’ve gone live. But, oh no, the client is reporting some bugs on the new site. Since you've built a robust collection of authorable components, you can't remember which component the bug is actually in. Even worse, your Support Team has taken over the project after launch, and they have even less of an idea what's causing the issue than you do!
The fix for this is super simple, and will add a total of 5 seconds per component to your development time. We can create a custom data property to house the name of our components! data-components
is the name I'm using, but if you would rather use something else, feel free.
For top level components, (components that are the parent inside their .tsx
file) you use the full name of the component/function! In the example below, just replace ComponentName
with the actual name of your component.
Use this method if you only have 1 component inside your .tsx
file, or this is the top level component in your .tsx
file.
return (
<div className="flex flex-col gap-6" data-component="ComponentName">
...
</div>
);
For any child components that are in the same .tsx file as the parent, you should use both the parent and child name, using an underscore to differentiate between the two. The important part: This is only for when you have 2 components in the same file, not for every time a component is a child of another component.
Use this method if you have more than 1 component inside your .tsx
file, and this component isn't the top level component in your .tsx
file.
return (
<div className="flex flex-col gap-6" data-component="ParentName_ChildName">
...
</div>
);
Visualize this: You’ve built a collection of complex Sitecore components, and you're finally ready for deployment. However, after users start interacting with your components, they begin reporting performance issues and bugs! It turns out your team's code has deeply nested conditionals. Navigating through the code to find the bugs is monotonous and painstaking. The logic is hard to follow, and every small change results in another bug. Once again, your Support Team is also struggling to debug and understand the code, leading to more frustration and wasted time.
If
statements are exceptionally common, whether it's your bog-standard if/else
or a ternary
, I can almost guarantee that every semi-complex component has more than one if
statement in it. Nested conditional statements are extremely common, too; it doesn't take much to add a quick nested if
to handle a niche use case. The issue with this, as mentioned above, is that it reduces code legibility, making it much harder to quickly understand the logic.
The fix for this is also super simple: we can invert our if
statements, also known as using an Early Return. The idea is that by inverting the value we are looking for inside the conditional (e.g., using false
instead of true
), we can remove the concept of nested if
's altogether.
Here is a common example that might be prevalent in your XM Cloud JSS components. We are checking for a form submission inside a useEffect
, then checking for 3 things before setting the submission as a success.
*isSubmitted*
)useEffect(() => {
if (!sitecoreContext.PageEditing) {
if (isSubmitted) {
if (results?.status === 200) {
setIsSuccess(true);
return;
} else {
setError(results?.errorMessage?.value);
}
} else {
setError('Submission Failed');
}
}
/* eslint-disable react-hooks/exhaustive-deps */
}, [isSubmitted]);
Even though this code is generally easy to follow, I'm certain that you can see how a longer or even slightly more complex version of this code could cause issues. If we invert each of the checks inside each if statement, we can flatten this code and make it much easier to read and follow.
useEffect(() => {
if (sitecoreContext.PageEditing) return;
if (!isSubmitted) {
setError('Submission Failed');
return;
}
if (results?.status != 200) {
setError(results?.errorMessage?.value);
return;
}
setIsSuccess(true);
/* eslint-disable react-hooks/exhaustive-deps */
}, [isSubmitted]);
Pretty much every if statement can utilize this method to create more legible code, so the next time you write an if statement, try this method and see what you think!
#region
still works with VS Code! You just need to wrap your region
and endregion
comments around the code you want to section. VS Code will also add the table to the code view panel on the side of your solution.
//#region types
type Props = {
Name: Field<string>;
}
//#endregion
You should create a 2nd components folder for all your components that are not directly linked to a Sitecore rendering Item. This way, Sitecore won't add unneeded components to the component-factory. If you want to learn more about this, you can read my blog that goes more in detail here!
If you're a seasoned Next.js developer, you probably already know what Next/dynamic is - but (at the time of writing) it causes bugs and issues with Sitecore when deployed to a server. If you want to learn more about it, you can read my Sitecore & Next/Dynamic blog here!
Adding data-component labels and using early returns will significantly improve the legibility of your Sitecore JSS code. Hopefully, you can utilize this in your projects, and improve the debugging experience for everyone on your team!