Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Table of Contents:
Intro
Technical Overview
Practical Overview
Definition of Done
Sitecore
You will know your component is complete if it is properly formatted, you have the requisite files outlined in the previous section (where applicable), and your files are free of TypeScript and ESLint warnings. Additionally, the appearance of the component should match the look of the Abstract design if one is provided, and if any Acceptance Criteria is provided, that should be met as well. We prioritize accessibility as well, so your component should pass [WCAG2.1 a11y requirements](https: //www.w3.org/WAI/standards-guidelines/wcag/glance/). This can be validated via the Storybook plugin we have set up, as well as in the browser using Lighthouse.
Lastly, you will need to have written some unit tests to check the core functionality of your component and ensure that those are passing.
In summary, your component should do the following...
If you have met all of these requirements, then you, intrepid developer, have a component worthy of submission to PR!
< Previous Next >
Intro | Technical Overview | Practical Overview | Typescript | Sitecore | Definition of Done | Analytics
Adding analytics to a component is pretty straightforward,
First set up your analytics object in your composition
method:
Then import the track
object from src/lib/Analytics
into your component, and grab the analytics
data from the composition props. After that, simply attach a handler to the correct component node, to call the track.component
method and send the data to analytics:
When not in production, analytics data will be sent to the console instead of to Google. To verify that your analytics are being setup and used correctly, simply open the console, trigger the analytics method, and you should see something similar to the following:
Intro | Technical Overview | Practical Overview | Typescript | Sitecore | Definition of Done | Analytics
Table of Contents:
Intro
Technical Overview
Practical Overview
Definition of Done
Sitecore
If you'd prefer to get right to the point and skip the overview, there's a handy checklist here. Otherwise, read on for an in-depth explanation of how one could approach a workflow via Storybook.
As a developer, you may find it convenient to develop your React component in isolation within Storybook, rather than developing on the page. This can give you the opportunity to preview it and get a feel for the data you will need. Once the component looks and behaves in the intended manner, it should be relatively simple to incorporate it into the broader application.
Where before we have focused on a logical overview of how components work and are used within the context of our Sitecore JSS setup and our custom React application, this section will focus on a practical suggested workflow for developing your component.
Whether or not you elect to decide to develop your React component with Storybook, you will need two things to get started: an index.tsx
and the data to render with it (if your component gets data from Sitecore).
It will be challenging to know in advance the shape of the data that comes to your React component from Sitecore, so you may find it helpful to set up your component in a very basic way that simply accepts props and renders or logs them out. Then, you can set up a composition function that does the same.
Once your component is rendering, you can capture the data from Sitecore that is logged or displayed onscreen to create your data file. Then you can begin working on your composition function to ensure you are sending only the data your component needs in the simplest, flattest form possible.
As you consider the data your component will need, it might be a good time to think about how your component is supposed to behave and consider writing out some assertions to test against in your test.ts
file.
After that, you can work in Storybook by importing your component's composition function into your story.js
file and process your dummy data with it. At this point, you will have dummy data that looks just like what is coming from Sitecore and you can develop your component in Storybook, just as you would a regular website.
An example of that might look something like this:
Finally, once your component is close to completion, you can finish writing your unit tests to ensure your component functions as expected.
The following section summarizes things into a concise checklist.
< Previous Next >
Intro | Technical Overview | Practical Overview | Typescript | Sitecore | Definition of Done | Analytics
Table of Contents:
Intro
Technical Overview
Practical Overview
Definition of Done
Sitecore
The Generate Component Factory (scripts/generate-component-factory.js
) generates the /src/temp/componentFactory.js
file which maps React components to JSS components.
The component factory is a mapping between a string name and a React component instance. When the Sitecore Layout service returns a layout definition, it returns named components. This mapping is used to construct the component hierarchy for the layout.
The default convention uses the parent folder name as the component name, but it is customizable in generateComponentFactory().
Sometimes Sitecore references a component in a way that is different from what we want the component to be called within the application. In this case, we can provide an alias to map the Sitecore name to our component upon import:
In this case, we are telling our app that if it receives a string called HeroCarousel
or HeroCarouselNocache
, use the 'Hero'
component. Likewise, if a string of JssAccordion
is encountered, use the 'Accordion'
component, and so on.
If the name of your component and its Sitecore counterpart are the same, there is no need to include an alias.
At its simplest, the goal of the composition file is to transform the data being passed to your component from accessing deeply nested properties like this:
into this:
What does that entail exactly?
The composition file also exists in the your component directory. Sitecore sends a wealth of information down to the page related to each component. Not all of this information is needed or even useful. So the purpose of each of these functions is to strip away the unneeded data, giving our component only what it needs to render properly.
To illustrate this, in the following example, the QuickLinks component will get a single items
prop returned to it, which will consist of an array of objects:
As a developer, you will be responsible for writing the composition function for your component. Since the data from Sitecore comes in all sizes and shapes, there is no "one-size-fits-all" solution, but most likely you can take a cue from the composition functions that have been written before to get a feel for how to approach a new one.
Now that you know how components are implemented within our app, how is a component actually created within the app?
Generally, each component you create will consist of at least one of the following items:
an index.tsx
file - your React file.
a composition.tsx
file for transforming incoming data into more concise props
a test.tsx
file - a file for your unit tests.
a types.ts
file - for Typescript definitions and interfaces
a stories.js
file - for Storybook..
a data.js
file - for mock Sitecore data.
a 📁 containing each of these files - It's a folder.
Read on for more detail.
Index.tsx
The index file will be your main component React file, using Typescript. At a minimum, your component will require this file. Since our project uses Tailwind
, your styles will mainly exist here as well. See the styles section for more info.
Test.tsx
The test file is where your unit tests live. Tests are written in React with Typescript
, using [Jest](https: //jestjs.io/en/) and [Enzyme](https: //enzymejs.github.io/enzyme/).
Jest is a popular testing library and Enzyme adds some sugar on top to make writing the tests a little easier.
You should be testing the basic functionality of your component. This may be as simple as validating that your component is rendering to mocking data and checking to make sure your component is outputting it correctly.
In all likelihood, you will need a test for every component you write, even if it is a very small test to confirm that the component is properly mounted.
Types.ts
This file is for type definitions and interfaces for [Typescript](https: //www.typescriptlang.org). You can store your component-specific definitions in this file and export them to your index file.
For more information on writing Typescript within our app, please check out our Typescript Style Guide.
Stories.js
The stories.js
file creates a Storybook component. To be honest, the paradigm of writing in Storybook can be a little bit tricky to grasp at first if you don't have experience with it. And to be frank, their docs could use some work. So you are encouraged to check out our documentation for Storybook..
In essence, however, consider your Storybook file something like an environment for your React component that enables you to run it in isolation from the rest of the app. This makes it easy to preview the functionality and, as a result, developers and designers can easily access the React component without having to navigate to a route to interact with it. This also enables you to view and manipulate it in ways that would be difficult in the context of an entire app.
If your component is extremely simple and self-contained, a Storybook file may not be necessary, or perhaps even possible. But in general, all components should have a Storybook file.
Unlike most of our other component files, we are not using Typescript in Storybook, so it is not necessary to provide types within your story file.
Data.js
The data.js
file is meant to provide mock data to your unit tests and Storybook files. It is ignored by Webpack, so don't include any objects or functions your component needs in order to render properly.
The data file does not use Typescript since it is generally only used to provide mock JSON data.
Perhaps the most frequent use case for this file is that you can copy/paste the data exactly as it comes from Sitecore. Since Storybook files and unit tests exist in isolation, they won't receive Sitecore data. But your React component will be relying on data to render correctly. So the dummy data placed within the data file ensures your React component will still have similar data in the same shape as the Sitecore data it would have in real-world conditions. Thus, even in isolation, you can ensure your component looks and behaves in a consistent and predictable manner.
On occasion, you may encounter a situation where you have a hard-coded object or map that is used for reference within your app. While these can be useful, sometimes they may clutter up your main index.tsx
file. In this case, you may be tempted to house those values in the data.js
file and import them into your React component from there. But as was mentioned above, these files are ignored by Webpack, so any necessary additional data you would want to exist in a file should be added to a file named something other than data.js
.
Depending on the complexity of your component, this file may not be necessary. For example, if your React component doesn't get called from Sitecore, doesn't have JSS fields, or it doesn't require any extra hard-coded data, then you will not need a data file.
Of course, all of these files must live somewhere, and that place is in a folder. This folder should of course be named after your component and added to the /components
directory. Resist the temptaion to take creative liberties with the name of the folder, as this will be the folder that will be imported into the Component Factory (see /src/temp/componentFactory.js
) and importing a folder named TheGreatestComponentYouHaveEverFeastedYourMiserableEyeballsOn
for the Modal component won't make a lot of sense out of context, no matter how fitting it seemed in the moment.
< Previous Next >
Intro | Technical Overview | Practical Overview | Typescript | Sitecore | Definition of Done | Analytics
Table of Contents:
Intro
Technical Overview
Practical Overview
Definition of Done
Sitecore
To understand how a component is displayed within our application, it helps to understand the process by which it is rendered within our React app.
This is a somewhat complex process, but the simplified overview is this:
When a user navigates to a route, the React app receives a big bundle of data from Sitecore, including a list of components, and the relevant data for those components.
That list represents the building blocks of the page that the user has navigated to.
Those "building blocks" are checked against the component list of our application, and when a match is found, a React component is returned, along with the data that Sitecore sent along with the component that it needs to render properly.
If a match is not found, a "placeholder component" is rendered instead. Within the React app, this is exactly what it sounds like: a big, ugly "placeholder" to remind you that this component has not yet been created for the app:
Oops! 🙀 we dont have Global Alerts yet!\
Let's dive in and get a little more insight.
Next >
Intro | Technical Overview | Practical Overview | Typescript | Sitecore | Definition of Done | Analytics
Table of Contents:
Intro
Technical Overview
Practical Overview
Definition of Done
Sitecore
In the context of our application, we treat Sitecore like a CMS for our React front end. We use it to tell our application where components should be and provide data and assets.
But Sitecore is not for the faint of heart. Many devs like to get their hands dirty by just "getting in there" and poking around. However, due to its terrible UI and grinding sluggishness, working within Sitecore can be maddening. To top it all off, as is so often the case, the documentation for Sitecore is substandard. God willing, you won't need to venture into Sitecore very often. But if you have exhausted all other options and you still find you need to work within it, it's better to go in with a clear gameplan of what you want to accomplish and how to accomplish it. This section aims to help you with that.
Once upon a time, new components were built by the front end team and then handed off to the Sitecore developers for integration into the application. These days, components built by the front end team stay within the front end application, making the workflow much more efficient. New components can then be integrated into the CMS for use by the content team, with editable fields intact.
While many components are already available for our application in Sitecore, if you find that you need to add a component to be edited within Sitecore, this document contains an overview to the process you will need to follow.
Before delving into that, it is helpful to understand at a high level how Sitecore is being used in our implementation.
A "page" such as /Home
or /Billing
consists of a collection of Renderings within Sitecore. A rendering could be viewed as a representation of a React component within Sitecore. These renderings are associated with data relevant to the component and placeholder info. A Placeholder is a way for content authors and marketing folks to specify where upon a page a component should be injected. In order for a rendering to be displayed upon a page, it will need to be assigned a placeholder.
When a page exists within Sitecore, it is made available to our application via something called the Layout Service, which exposes an endpoint that can be requested. This endpoint returns a serialized JSON payload of the rendering info from Sitecore. While a traditional Sitecore implementation would involve C# and Razor templates, this implementation makes it possible for us to use React on the front end.
Navigate to [Sitecore](http: //scdev25.duke-energy.com/sitecore) and login. From there, expand "sitecore > Layout > Renderings > Custom > Common" and you can see the available renderings. If you need a rendering to map to your component that isn't already available here, you can create one.
Create a Rendering. Within the appropriate folder under /sitecore/layout/renderings
, create a new Json Rendering
. This will most likely be within the Custom/Common folder, and can be done either by right-clicking the folder and selecting Insert > Json Rendering or selecting the folder you want to create a rendering in and then pressing the Json Rendering
button from the options.
You will be prompted by a modal to choose a name for your item. In the input labelled "Enter a name for the new item", provide the name of the React component that will be used for the rendering.
You can now add your newly-created Json Rendering to a page. If appropriate, you will also need to specify a datasource item for the rendering. The datasource item will need to be created from a data template in Sitecore.
When Layout Service is rendering, the fields from the datasource item will be serialized and added to the Layout Service output and should now be available to our application.
< Previous
Intro | Technical Overview | Practical Overview | Typescript | Sitecore | Definition of Done | Analytics