2

I am building a site with Gatsby and so far I find programmatically creating pages a very handy feature. You can have a category template and have gatsby-node create pages for each content category very easily. However, what is the recommended way to add differentiated content to that same template?

Right now I'm using ternary operators to check which category it is and add specific content based on that precise category (a few examples of content that needs to be differentiated accordingly: category intro title, SEO title and SEO description inside the SEO component based on Helmet)

inside categoryTemplate.js

const booksTitle = "Quote on books"
const songsTitle = "Quote on songs"
const travelsTitle = "Quote on travels"
const booksSeoTitle = "Books Title for SEO"
...

               <CategoryIntro
                    title={<>
                        {category === "books"
                        ? booksTitle
                        : category === "songs"
                        ? songsTitle
                        : category === "travels"
                        ? travelsTitle
                        : null
                        }
                    </>}
              />

This approach actually works, but I wonder if there's a more convenient practice that I could use? Should I store information about categories elsewhere in a json format instead of having them declared in the template file?

Thanks a lot.

Giulia
  • 765
  • 2
  • 8
  • 33
  • I would assign `title` outside of the template, as a `let title = ''` and a `switch(category) { ... }`, then, inside the template `title={title}` – Ignacio Lago Aug 16 '19 at 18:19

1 Answers1

2

I think the approach you suggested about storing that information elsewhere would make the code cleaner and easier to maintain. The template component should only be a generic template as it is intended. You shouldn't mix it with content.

How about a categories.js file?

export const categories = {
  book: {
    title: "Quote on books",
    seoTitle: "",
  },
  songs: {
    title: "Quote on songs",
    seoTitle: "",
  },
}

Import your categories.js in your template file and let it decide which category to choose via a prop:

import { categories } from "./categories.js"

// This function returns your mediaType object
function getObject(obj, mediaType) {
  return obj[mediaType];
}

function MediaTemplate({ mediaType }) {

  const category = getObject(mediaType);
  // See this answer for how to access the object key dynamically: https://stackoverflow.com/questions/4255472/javascript-object-access-variable-property-by-name-as-string

  console.log("category:");
  console.log(category);

  // It is only one amazing line now!
  return (
    <CategoryIntro title={category.title} />
  );
}
EliteRaceElephant
  • 7,744
  • 4
  • 47
  • 62
  • Hello, thanks a lot! I like this approach but I think I'm not accessing the object key in the right way, because I get the error 'Cannot read property of undefined'. Any clue on what may be the issue? I checked the answer you linked, but even though it looks I'm doing what suggested there, it doesn't seem to work. – Giulia Aug 16 '19 at 19:59
  • @Giulia I tested it myself and edited my answer for the correct solution. =) – EliteRaceElephant Aug 16 '19 at 21:21
  • 1
    Thank you very much!! It works perfectly :) (Excuse the late reply, was away from PC) – Giulia Aug 19 '19 at 07:53