One of the big changes that we’ve found when developing with Sitecore and NextJS (using the Sitecore First approach) is handling nulls in the front end. Traditionally, front-end devs would build the pretty looking website with the “happy path”, then Sitecore devs would be at the end of the development chain to wire it up, making sure to build in reliability. Now that the front-end is the last step in the development chain, that responsibility falls on the front-end devs. In addition to whatever can go wrong will go wrong, there are several known conditions with the Sitecore data that need to be handled.

  • The component has been added to the page, but no datasource has been set.
  • The component is being used in Experience Editor mode.
  • The component datasource template has had a field removed / renamed.

There are probably some others too. The point is, that no matter what happens, we don’t want the whole page to fall over because of an exception in a single component. In Sitecore MVC, we would create extension methods that help us to get the most useful value possible back from a field, which might just be ‘’.

In C#, this would look something like…

var buttonText = sitecoreItem.GetTextField("buttonText", string.Empty);
var buttonLink = sitecoreItem.GetLinkField("buttonLink", string.Empty);

In later iterations, we would map the fields to a class to make the code tidier and easier to maintain, but you get the idea. In NextJS I’d like to get to the same level of abstracting away the code that does this mapping. It’s not quite there yet, but this gives us a good starting point.

Here’s a snippet of how we’re handling this in our JSS adapters…

const ButtonJSSAdapter = ({
  fields,
}: ButtonJSSAdapterProps): React.ReactElement | null => {
  // if the fields are null, then there's no point proceeding to try to map the values.
  // However, we might be in Experience Editor mode, in which case we want to show the component so that the content authors can edit it.
  if (!fields && !isEditorActive()) {
    return null;
  }

  // try to get a TextField from the buttonText field on the fields object. If not, return an empty string.
  const buttonText = getField<TextField>(fields, 'buttonText', '');
  // try to get a LinkField from the buttonUrl field on the fields object. If not, return an empty string.
  const buttonLink = getField<LinkField>(fields, 'buttonUrl', '');
};

The getField method looks like this…

export const getField = <returnType, dataType = string>(
  fields: any,
  key: string,
  fallback: dataType
): returnType => {
  if (fields && fields[key] && fields[key].value !== '') {
    return fields[key] as unknown as returnType;
  }

  return {
    value: fallback,
  } as returnType;
};

As I said, there’s a little way to go to make it as clean as the C# version, but this is keeping our pages from falling over.

I hope this has been helpful. Thanks for reading. :-)