Hey, it's been a little bit since the last post in this series. If you missed my SUGCON EU 2019 posts and are interested in some of the things I learned/talked about there, you can check them out here.

Last post we finished up the homepage components with a "Recent Posts" component. It's time to move on though. It's time to lay the foundation for building out other pages. I also took the opportunity to refactor some existing things. I wasn't happy with how some components were named and I wanted to clean up some GraphQL queries. I also wanted to write a GraphQL query to power the global header.

As always, you can check out the full source code for the app on GitHub.

Definition Naming

It was starting to get a little confusing when dealing with different data types so I chose to name all of the components, routes and templates consistently. If you browse the definition folder now you'll see that all of the types have what type they are in their name. I kind of got this idea by how the starter React JSS app names it's templates.

You'll notice all of the components defined in the data folder were updated to account for this naming convention change.

Header GraphQL

When we originally built out the header we were still living the dream in disconnected mode. Things have changed, we've gone connected and we can now take advantage of the GraphQL services. The header is now built into our Layout component:

src/Layout.js

const Layout = ({ route }) => (
  <React.Fragment>
    <VisitorIdentification />
    <div className="container">
      <Header />
      <Placeholder name="jss-main" rendering={route} />
    </div>
  </React.Fragment>
);

Doing this will allow the header to just appear on newly created pages and we won't need to rely on content authors to add it every time.

Moved Content

All of the listing pages were moved to a Tags folder in the routes directory. Originally I was thinking we would just have a single listing page that sourced the tags from the content folder but I think it makes more sense to have them be individual pages. I added a route type to accommodate this.

sitecore/definitions/routes/ListingPage-Route.sitecore.js

import { CommonFieldTypes } from '@sitecore-jss/sitecore-jss-manifest';

export default function(manifest) {
  manifest.addRouteType({
    name: 'ListingPage-Route',
    fields: [{ name: 'title', type: CommonFieldTypes.SingleLineText }],
  });
}

From the JSS documentation, addRouteType is described as this:

addRouteType(...routeTypes: template[]): adds a Sitecore template type for a route

Listing page routes have been converted to use this route type as well. Check out "Sitecore JavaScript Services - Creating Custom Routes and Displaying Route-Level Fields in Components" by Anastasiya Flynn for some more information about routing.

Refactored GraphQL queries

I refactored some of the existing components that were using the Query component from react-apollo. I switched over to using the GraphQLData component that comes with the Sitecore JSS App. Overall, this technique reduces the size of your components and it allows you to just receive the GraphQL query data in your component props.

src/components/RecentPosts-Component/index.js

const RecentPosts = ({ postQuery }) =>
  <React.Fragment>
    {postQuery.search && <PostListing posts={postQuery.search.results.items} />}
  </React.Fragment>
  ;

export default GraphQLData(GET_RECENT_POSTS_QUERY, { name: 'postQuery', options: { variables: { howMany: 5 } } })(RecentPosts);

Conclusion

This post was a mix of forward progress and cleaning up some existing components. By adding the new route type and moving our listing pages, we should be able to at least navigate to the listing pages and see the global header on each. The next post is going to start defining these pages more by adding a listing on each.