Simone Foschi
Frontend Developer
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
1module.exports.createPages = async ({ graphql, actions }) => {
2 const { createPage } = actions
3 const blogTemplate = path.resolve("./src/templates/blog.js")
4 const res = await graphql(`
5 query {
6 allMarkdownRemark{
7 edges {
8 node {
9 fields {
10 slug
11 }
12 }
13 }
14 }
15 }
16 `)
17
18 const posts = res.data.allMarkdownRemark.edges
19
20 posts.forEach((edge, index) => {
21 createPage({
22 component: blogTemplate,
23 path: `/${edge.node.fields.slug}`,
24 context: {
25 slug: edge.node.fields.slug,
26 },
27 })
28 })
29}
Che ho modificato in
1module.exports.createPages = async ({ graphql, actions }) => {
2 const { createPage } = actions
3 const blogTemplate = path.resolve("./src/templates/blog.js")
4 const res = await graphql(`
5 query {
6 allMarkdownRemark(filter: {frontmatter: {update: {ne: null}, published: {eq: true}}}, sort: {fields: [frontmatter___update, frontmatter___date], order: ASC}) {
7 edges {
8 node {
9 fields {
10 slug
11 }
12 }
13 }
14 }
15 }
16 `)
17
18 const posts = res.data.allMarkdownRemark.edges
19
20 posts.forEach((edge, index) => {
21 const previous = index === 0 ? null : posts[index - 1].node
22 const next = index === posts.length - 1 ? null : posts[index + 1].node
23
24 createPage({
25 component: blogTemplate,
26 path: `/${edge.node.fields.slug}`,
27 context: {
28 slug: edge.node.fields.slug,
29 next,
30 previous,
31 },
32 })
33 })
34}
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
1const Blog = props => {
2 var page_context = props.pageContext
3 ...
4 return (
5 ...
6 <div className="blog-post-nav">
7 <Link to={`/$page_context.previous == null ? "" : page_context.previous.fields.slug}`} className={page_context.previous || "hideme"}>
8 ‹ prev
9 </Link>
10 <Link to={`/$page_context.next == null ? "" : page_context.next.fields.slug}`} className={page_context.next || "hideme"}>
11 next ›
12 </Link>
13 </div>
14 ...
15 )
16}
-- Buona vita --