简体   繁体   中英

Passing context from gatsby-node.js into react components (pagination/navigation link troubleshooting)

I'm currently building a website for a client with Gatsby and Wordpress as a CMS. All has gone well so far but I am struggling with creating the "previous page" and "next page" links while finalizing pagination for the site's blog. I think I know what direction I'm heading in next, but I am struggling with passing items through context in my gatsby-node.js file.

Relevant parts of gatsby-node.js:


const path = require('path')


module.exports.createPages = async ({ graphql, actions }) => {

  const { createPage } = actions
  const blogPostTemplate = path.resolve('./src/templates/blog-post.js')
  const blogCategoryFilter = path.resolve('./src/templates/blog-filter-category.js')
  const blogArchiveFilter = path.resolve('./src/templates/blog-filter-archive.js')

  const blogList = await graphql(`
query {
  allWordpressPost {
    edges {
      node {
        slug
        date(formatString:"YYYY-MM")
      }
    }
  }
}
`);

  const categories = await graphql(`
query {
  allWordpressCategory {
    edges {
      node {
        slug
      }
    }
  }
}
`);

  const posts = blogList.data.allWordpressPost.edges;

categories.data.allWordpressCategory.edges.forEach((edge) => {
    const slug = edge.node.slug
    const blogPostsCount = posts.length
    const blogPostsPerPaginatedPage = 3
    const paginatedPagesCount = Math.ceil(blogPostsCount / blogPostsPerPaginatedPage)
    for (let i = 0; i <= paginatedPagesCount; i++) {
      createPage({
        component: blogCategoryFilter,
        path: i === 0 ? `/blog/category/${slug}` : `/blog/category/${slug}/${i + 1}`,
        context: {
          slug: slug,
          limit: blogPostsPerPaginatedPage,
          skip: i * blogPostsPerPaginatedPage,
          paginatedPagesCount,
          currentPage: i + 1,
        }
      })
    }
  })

My template file:

import React from 'react'
import { graphql, Link } from 'gatsby'

import Layout from '../components/layout'
import BlogNav from '../components/blognav'

import blogStyles from '../components/modules/blog.module.css'

export const query = graphql`
  query($slug: String!, $limit: Int!, $skip: Int!) {
    allWordpressPost (filter: {categories: {elemMatch: {slug: { eq: $slug }}}} limit: $limit skip: $skip) {
      edges {
        node {
          title
          slug
          content
          date(formatString: "MMMM DD, YYYY")
        }
      }
    }
    allWordpressCategory (filter: {slug: {eq: $slug}}) {
      edges {
        node {
          slug
        }
      }
    }
  }
`


export default ({ data }) => {


  return (
    <Layout>
      <div className={blogStyles.blog_container}>
        <div className={blogStyles.blogContent_container}>
          <ol>
            {data.allWordpressPost.edges.map((edge) => {
              return (
                <div className={blogStyles.blogPost_container}>
                  <li className={blogStyles.blog_list}>
                    <h2><Link to={`/blog/${edge.node.slug}`} className={blogStyles.blog_title} dangerouslySetInnerHTML={{ __html: edge.node.title }}></Link></h2>
                    <p className={blogStyles.blog_date}>{edge.node.date}</p>
                    <p className={blogStyles.blog_content} dangerouslySetInnerHTML={{ __html: edge.node.content }} />
                  </li>

                </div>
              )
            })}
          </ol>
        </div>
        <BlogNav />
      </div>
    </Layout>
  )
}

I want to incorporate some code like this:

class BlogList extends React.component {
  render() {
    const { currentPage, paginatedPagesCount } = this.props.pageContext
    const isFirst = currentPage === 1
    const isLast = currentPage === paginatedPagesCount
    const prevPage = currentPage - 1 === 1 ? "/" : (currentPage - 1).toString()
    const nextPage = (currentPage + 1).toString()

    return (
       // code to display a list of posts 
       {!isFirst && (
        <Link to={prevPage} rel="prev">
          ← Previous Page
        </Link>
      )}
      {!isLast && (
        <Link to={nextPage} rel="next">
          Next Page →
        </Link>
      )}
    )
  }
}

However, my component looks different and I'm not quite sure how to pull in the information I'm passing through context in this example. This line in particular trips me up:

const { currentPage, paginatedPagesCount } = this.props.pageContext

My error reads that it cannot read props of undefined. It appears I can't use "this"? I feel like I'm missing something foundational here. React makes my head spin sometimes!

Thoughts? Strategies? Thanks! Excuse any sloppy code: I'm a newbie.

Assuming BlogList would be BlogNav instead (because you are calling it from the template). What you could do is something like: - template file

 /** Your Query **/
export default ({ data, pageContext }) => {
 // here `this.props` won't work because this is not a class (unless you transform this to a react component)
 // your body

 <BlogNav {...pageContext} />
}

Then, in your BlogNav you will be able to call the properties as you are doing now.

It should work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM