Adding individual pages with SWR

As I add more content to the site, I'd like to be able to share direct links to posts. It's a pretty simple change to add individual changelog and blog pages. To start, I first had to decide on the URL structure, which had a natural choice, following best practice. I ended up with the following: https://tombates.co/{resource}/{slug}. With Next.js, all it takes to create dynamic routing is to create a new file inside the pages directory. For my changelog articles, the path looks like pages/changelog/[slug].tsx.

Then it's just a case of hooking up the data. Below is the skeleton for the page minus the details.

import React from "react";

const fetchData = async slug => {
  return Promise.resolve({ title: slug });
}

const ChangelogPage = ({ article }) => {
   if (!article) {
    return (<div>Article not found!</div>);
  }

  return (<article>{article.title}</article>);
};

ChangelogPage.getInitialProps = async ({ query }) => {
  const article = await fetchData(query.slug);
  return {
    article
  };
};

export default ChangelogPage;

Once I had the primary setup for the page in place, I wanted to look at using a brilliant library from Zeit called SWR, even if it's a little bit of overengineering. SWR is a React Hooks library for remote data fetching. It has a bunch of exciting features, including caching and fast page navigation. However, the feature I was mostly interested in was Revalidation on focus, which would allow me to edit my content on Contentful and instantly see updates when returning to my site.

Getting SWR setup is a piece of cake. All you need is one function call and to hook up the returned data.

import React from "react";
import useSWR from "swr";

const fetchData = async slug => {
  return Promise.resolve({ title: slug });
}

const ChangelogPage = ({ article, slug }) => {
  const { data } = useSWR(slug, fetchData, {
    initialData: article
  });

  if (!data) {
    return (<div>Article not found!</div>);
  }

  return (<article>{data.title}</article>);
};

ChangelogPage.getInitialProps = async ({ query }) => {
  const article = await fetchData(query.slug);

  return {
    article,
    slug: query.slug
  };
};

export default ChangelogPage;

And that's it. We're all setup with individual pages with almost live updates using SWR. You can find more examples of SWR here.