GatsbyJS博客中的分页

问题描述 投票:1回答:1

我在我的第一个GatsbyJS项目中创建了一个博客,我对React和Gatsby还是陌生的

博客本身运行良好,我正在通过markdown文件获取内容,但是我为使分页部分正常工作付出了很多努力。

我有4页blogTemplate(每个博客文章的模板),posts.js(在单个登录页面上循环并显示每个博客文章),blog.js(将所有博客文章以数组形式拉出从帖子页面并将其显示在卡片中)和我的gatsby-node.js页面(正在处理博客的graphql)

下面是我正在使用的所有文件的列表,最下面是我尝试实现的一些插件

blogTemplate.js

import React from "react";
import { graphql, Link } from "gatsby";
import { Container, Row, Col, Image } from "react-bootstrap";

import Layout from "../components/layout";

export default function Template({ data }) {
    const post = data.markdownRemark;
    const { markdownRemark } = data // data.markdownRemark holds your post data
    const { frontmatter, html } = markdownRemark
    const { title, author, date, thumbnail } = post.frontmatter;
    return (
      <Layout>
      <Container  className="px-0" >
      <Row>
        <Col>
          <Container className="mt-5 mb-5">
            <h1>{title}</h1>
    <p>Posted by {author} on {date} thumbnail {thumbnail}</p>
    <Image src={thumbnail} alt={thumbnail} fluid />
            <div dangerouslySetInnerHTML={{ __html: post.html }} />
            <Link to="/blog">Back to blogs</Link>
          </Container>
        </Col>
      </Row>
    </Container> 


        </Layout>
    )
  };

  export const postQuery = graphql`
  query BlogPost($path: String!) {
    markdownRemark(frontmatter: { path: { eq: $path }}) {
      html
      frontmatter {
        author
        date
        title
        path
        description
        thumbnail
      }
      html
    }
  }
`;

Posts.js

import React from "react"
import { Link } from "gatsby"
import { Card } from 'react-bootstrap';


const PostLink = ({ post }) => (
  <Card className="cardpadding">
      <Card.Img variant="top" src={post.frontmatter.thumbnail} alt={post.frontmatter.title} />
      <Card.Body className="dark-text">
        <p>{post.frontmatter.date}</p>
          <Card.Title>{post.frontmatter.title}</Card.Title>
          <Card.Text className="blue-text">
          <Link to={post.frontmatter.path} className="post-link">
            {post.frontmatter.title}
          </Link>
          </Card.Text>
      </Card.Body>
  </Card>
)
export default PostLink

blog.js

import React from "react"
import { graphql } from "gatsby"
import Post from "../components/post";
import Layout from "../components/layout"
import { Container } from "react-bootstrap";

const BlogPage = ({
  data: {
    allMarkdownRemark: { edges },
  },
}) => {

const Posts = edges
.filter(edge => !!edge.node.frontmatter.date) // You can filter your posts based on some criteria
.map(edge => <Post key={edge.node.id} post={edge.node} />)
console.log('Posts', Posts)

return (
  <Layout>
    <Container className="mt-5">
    <div className="grids">
      {Posts}
    </div>
    </Container>
  </Layout>
)
}

export default BlogPage
export const AllBlogsQuery = graphql`
  query AllBlogPosts {
    allMarkdownRemark(
      sort: { order: DESC, fields: [frontmatter___date] }
      ) {
      edges {
        node {
          id
          frontmatter {
            date(formatString: "MMMM DD, YYYY")
            title
            description
            author
            path
            thumbnail
          }
        }
      }
    }
  }
`

gatsby-node.js

const path = require("path");

exports.createPages = ({ actions, graphql }) => {
  const { createPage } = actions;
  const postTemplate = path.resolve("src/templates/blogTemplate.js");

  return graphql(`
  {
    allMarkdownRemark(
      sort: { order: DESC, fields: [frontmatter___date] }
      limit: 1000
    ) {
      edges {
        node {
          id
          frontmatter {
            path
          }
        }
      }
    }
  }
`).then(res => {
    if (res.errors) {
      return  Promise.reject(res.errors)
    }
    res.data.allMarkdownRemark.edges.forEach(({ node }) => {
      createPage({
        path: node.frontmatter.path,
        component: postTemplate,
        context: {}, // additional data can be passed via context
      })
    })
  })
};

我尝试了什么

我尝试在下面的gatsby-node文件中添加gatsby-paginate插件。但是,当我单击单个博客页面链接时,出现了404错误。

Gatsby-node.js

const path = require("path");
const paginate = require('gatsby-paginate')


exports.createPages = async ({ actions, graphql }) => {
  const { createPage } = actions;
  //const postTemplate = path.resolve("src/templates/blogTemplate.js");

  const ya = await graphql(`
  {
    allMarkdownRemark(
      sort: { order: DESC, fields: [frontmatter___date] }
      limit: 1000
    ) {
      edges {
        node {
          id
          frontmatter {
            path
          }
        }
      }
    }
  }
`);

paginate({
  createPage,
  items: ya.data.allMarkdownRemark.node,
  itemsPerPage: 2,
  pathPrefix: '/blog',
  component: path.resolve("src/templates/blogTemplate.js")
});

ya.data.allMarkdownRemark.node.map(articleData => 
      createPage({
        path: node.frontmatter.path,
        component: path.resolve("src/components/post.js"),
        context: {}, // additional data can be passed via context
    })
  );
}
javascript reactjs pagination gatsby
1个回答
0
投票

我解决了这个问题,该错误出在我的gatsby-node.js文件中。

将两个模板拆分成单独的变量,然后将数据传递到每个模板中,这是我想要实现的正确方法

请参见下面的gatsby-node.js文件

const path = require('path')
const { slugify } = require('./src/util/utilityFunctions')
const _ = require('lodash')

exports.onCreateNode = ({ node, actions }) => {
  const { createNodeField } = actions
  if (node.internal.type === 'MarkdownRemark') {
    const slugFromTitle = slugify(node.frontmatter.title)
    createNodeField({
      node,
      name: 'slug',
      value: slugFromTitle,
    })
  }
}

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

  // Page templates
  const templates = {
    post: path.resolve('src/templates/single-post.js'),
    postList: path.resolve('src/templates/post-list.js')
  }

  const res = await graphql(`
    {
      allMarkdownRemark {
        edges {
          node {
            frontmatter {
              author
              tags
            }
            fields {
              slug
            }
          }
        }
      }
    }
  `)

  if (res.errors) return Promise.reject(res.errors)

  // Extracting all posts from res
  const posts = res.data.allMarkdownRemark.edges

  // Create single post pages
  posts.forEach(({ node }) => {
    createPage({
      path: node.fields.slug,
      component: templates.post,
      context: {
        // Passing slug for template to use to fetch the post
        slug: node.fields.slug
      },
    })
  })

  // Create posts pagination pages
  const postsPerPage = 4
  const numberOfPages = Math.ceil(posts.length / postsPerPage)

  Array.from({ length: numberOfPages }).forEach((_, index) => {
    const isFirstPage = index === 0
    const currentPage = index + 1
    // Skip first page because of index.js
    if (isFirstPage) return

    createPage({
      path: `/page/${currentPage}`,
      component: templates.postList,
      context: {
        limit: postsPerPage,
        skip: index * postsPerPage,
        numberOfPages: numberOfPages,
        currentPage: currentPage,
      },
    })
  })
}
© www.soinside.com 2019 - 2024. All rights reserved.