Simone Foschi

Frontend Developer

‹ Back to Blog index


Come usare il context di Gatsbyjs per la navigazione nel blog

Simo 2020/4/1

updated 2020/4/2


Come è nata l'idea

Nel mio caso specifico volevo inserire i pulsanti precedente e successivo negli articoli per facilitarne la consultazione.

Il context di Gatsby

Gatsbyjs ha un suo context specifico al quale è possibile accedervi tramite GraphQL.

Per chi non lo sapesse, il context sono delle informazioni personalizzate che un framework si porta dietro per essere usato nei vari componenti che ne hanno necessità.

Nello specifico, Gatsby ha un context interno, accessibile tramite le props (props.pageContext.tuocontext), che bisognerà valorizzare nella procedura onCreatePage dentro gatsby-node.js e sarà disponibile in tutte le pagine.

Fate riferimento a questa pagina del blog ufficiale per ulteriori dettagli, che dice tra le altre cose:

Siccome il context di Gatsby è serializzato prima di essere passato alle pagine, non si potranno passare delle funzioni ai componenti.


Come ho creato un context in Gatsby per il template dei post del mio blog

Nel file gatsby-node.js avevo già pronta la seguente procedura

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
module.exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const blogTemplate = path.resolve("./src/templates/blog.js")
  const res = await graphql(`
    query {
      allMarkdownRemark{
        edges {
          node {
            fields {
              slug
            }
          }
        }
      }
    }
  `)

  const posts = res.data.allMarkdownRemark.edges

  posts.forEach((edge, index) => {
    createPage({
      component: blogTemplate,
      path: `/${edge.node.fields.slug}`,
      context: {
        slug: edge.node.fields.slug,
      },
    })
  })
}

Che ho modificato in

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
module.exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const blogTemplate = path.resolve("./src/templates/blog.js")
  const res = await graphql(`
    query {
      allMarkdownRemark(filter: {frontmatter: {update: {ne: null}, published: {eq: true}}}, sort: {fields: [frontmatter___update, frontmatter___date], order: ASC}) {
        edges {
          node {
            fields {
              slug
            }
          }
        }
      }
    }
  `)

  const posts = res.data.allMarkdownRemark.edges

  posts.forEach((edge, index) => {
    const previous = index === 0 ? null : posts[index - 1].node
    const next = index === posts.length - 1 ? null : posts[index + 1].node

    createPage({
      component: blogTemplate,
      path: `/${edge.node.fields.slug}`,
      context: {
        slug: edge.node.fields.slug,
        next,
        previous,
      },
    })
  })
}

Inserimento dei pulsanti

Ho dato un ordinamento per data ai post in allMarkdownRemark, controllando che next e previous non vadano fuori dal numero delle pagine e aggiungendo sempre le variabili next e previous con assegnati gli oggetti node al context nella procedura createPage.

Nel template delle pagine del blog ho aggiunto i pulsanti html valorizzati tramite props.pageContext

ho eliminato il codice dal file './src/templates/blog.js' che non è pertinente con l'articolo


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Blog = props => {
    var page_context = props.pageContext
    ...
    return (
        ...
        <div className="blog-post-nav">
            <Link to={page_context.previous == null ? "" : page_context.previous.fields.slug} className={page_context.previous || "hideme"}>
                ‹ prev
            </Link>
            <Link to={page_context.next == null ? "" : page_context.next.fields.slug} className={page_context.next || "hideme"}>
                next ›
            </Link>
        </div>
        ...
    )
}

-- Buona vita --

‹ prevnext ›

‹ Back to Blog index