Как отобразить похожие сообщения на основе тегов текущего сообщения с помощью Gatsby? - PullRequest
0 голосов
/ 30 мая 2019

В нижней части каждой страницы сообщений моего сайта я хочу отобразить соответствующие сообщения на основе тегов текущих сообщений.Например, если у меня есть сообщение с тегом «собака», я хочу отобразить как 4 сообщения с тегом «собака» на странице сообщения.

Я пробовал подход , ноКажется, я не могу заставить его работать ... Я не получаю никаких ошибок, но relatedPosts в шаблоне поста пуст, поэтому ничего не отображается.Любые идеи о том, что я делаю не так?

Связанные компонента сообщения

import React from 'react'
import * as PropTypes from 'prop-types'
import Link from 'gatsby-link'

const RelatedPosts = ({ posts }) => (
  <section className="sidebar-section">
    <h2 className="section-title separator-below">Read next</h2>
    <section className="section-content">
      <p>Here are a couple of related posts you will enjoy reading.</p>
      {/* <ul> */}
      {posts.map(post => (
        <p key={post.id || post.node.id}>
          <Link
            className="custom-link"
            to={`${post.slug || post.node.slug}`}
          >
            {post.title || post.node.title}
          </Link>
        </p>
      ))}
      {/* </ul> */}
    </section>
  </section>
)

export default RelatedPosts

Шаблон сообщения

import React from 'react'
import { graphql } from 'gatsby'
import Helmet from 'react-helmet'
import config from '../utils/siteConfig'
import Layout from '../components/Layout'
import Hero from '../components/Hero'
import Container from '../components/Container'
import PageBody from '../components/PageBody'
import TagList from '../components/TagList'
import PostLinks from '../components/PostLinks'
import PostDetails from '../components/PostDetails'
import SEO from '../components/SEO'
import Disqus from 'gatsby-plugin-disqus'
import styled from 'styled-components'
import RelatedPosts from '../components/RelatedPosts'


const DisqusWrapper = styled.div`
  margin: 0 auto;
  max-width: ${props => props.theme.sizes.maxWidthCentered};
  padding-top: 3rem;
`

const PostTemplate = ({ data, pageContext }) => {
  const {
    title,
    slug,
    heroImage,
    body,
    publishDate,
    tags,
  } = data.contentfulPost
  const postNode = data.contentfulPost

  const previous = pageContext.prev
  const next = pageContext.next

  const relatedPosts = pageContext.relatedPosts


  return (
    <Layout>
      <Helmet>
        <title>{`${title} - ${config.siteTitle}`}</title>
      </Helmet>
      <SEO pagePath={slug} postNode={postNode} postSEO />

      <Container>
      <PostDetails
          title={title}
          date={publishDate}
          timeToRead={body.childMarkdownRemark.timeToRead}
          tags={tags}
        />

      </Container>

      <Hero image={heroImage} height={'80vh'} />

      <Container>
        <PageBody body={body} />
        <DisqusWrapper>
          <Disqus
            identifier={slug}
            title={title}
            url={`${config.siteUrl}${slug}`}
          />
        </DisqusWrapper>
        <RelatedPosts posts={relatedPosts} />
      </Container>
    </Layout>
  )
}

export const query = graphql`
  query($slug: String!) {
    contentfulPost(slug: { eq: $slug }) {
      title
      slug
      metaDescription {
        internal {
          content
        }
      }
      publishDate(formatString: "MMMM DD, YYYY")
      publishDateISO: publishDate(formatString: "YYYY-MM-DD")
      tags {
        title
        id
        slug
      }
      heroImage {
        title
        fluid(maxWidth: 1800) {
          ...GatsbyContentfulFluid_withWebp_noBase64
        }
        ogimg: resize(width: 1800) {
          src
          width
          height
        }
      }
      body {
        childMarkdownRemark {
          timeToRead
          html
          excerpt(pruneLength: 320)
        }
      }
    }
  }
`

export default PostTemplate

gatsby-node.js

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

  const loadPosts = new Promise((resolve, reject) => {
    graphql(`
      {
        allContentfulPost(
          sort: { fields: [publishDate], order: DESC }
          limit: 10000
        ) {
          edges {
            node {
              slug
              publishDate
              tags {
                title
                id
                slug
              }
            }
          }
        }
      }
    `).then(result => {
      const posts = result.data.allContentfulPost.edges

      // Create main home page
      createPage({
        path: `/`,
        component: path.resolve(`./src/templates/index.js`),
      })

      const sortByDateDescending = (a, b) => {
       const aPubDateInMS = (new Date(a.publishedOn)).getTime();
       const bPubDateInMS = (new Date(b.publishedOn)).getTime();

       if (aPubDateInMS > bPubDateInMS) {
         return 1
       }

       if (aPubDateInMS < bPubDateInMS) {
         return -1
       }

       return 0
     }

      const getRelatedPosts = (currentPost, posts) => {
          const MINIMUM_CATEGORIES_IN_COMMON = 1

          const hasAtLeastOneCategoryInCommon = ({ node }) => {
            // stop working if we're looking at the same article
            if (currentPost.id === node.id) {
              return false
            }
            const commonCategories = _.intersectionBy(currentPost.tags, node.tags, (tags) => tags.slug)
            return commonCategories.length >= MINIMUM_CATEGORIES_IN_COMMON
          }

          const filteredResults = posts.filter(hasAtLeastOneCategoryInCommon)
          if (filteredResults.length > 5) {
            return filteredResults.sort(sortByDateDescending).slice(0, 5)
          }
          return filteredResults
        }

      // Create each individual post
      posts.forEach((edge, i) => {
        const prev = i === 0 ? null : posts[i - 1].node
        const next = i === posts.length - 1 ? null : posts[i + 1].node
        createPage({
          path: `${edge.node.slug}/`,
          component: path.resolve(`./src/templates/post.js`),
          context: {
            slug: edge.node.slug,
            prev,
            next,
            relatedPosts: getRelatedPosts(edge.node, result.data.allContentfulPost.edges),
          },
        })
      })
      resolve()
    })
  })

  const loadTags = new Promise((resolve, reject) => {
    graphql(`
      {
        allContentfulTag {
          edges {
            node {
              slug
              post {
                id
              }
            }
          }
        }
      }
    `).then(result => {
      const tags = result.data.allContentfulTag.edges
      const postsPerPage = config.postsPerPage

      // Create tag pages with pagination if needed
      tags.map(({ node }) => {
        const totalPosts = node.post !== null ? node.post.length : 0
        const numPages = Math.ceil(totalPosts / postsPerPage)
        Array.from({ length: numPages }).forEach((_, i) => {
          createPage({
            path:
              i === 0 ? `/tag/${node.slug}/` : `/tag/${node.slug}/${i + 1}/`,
            component: path.resolve(`./src/templates/tag.js`),
            context: {
              slug: node.slug,
              limit: postsPerPage,
              skip: i * postsPerPage,
              numPages: numPages,
              currentPage: i + 1,
            },
          })
        })
      })
      resolve()
    })
  })

  return Promise.all([loadPosts, loadTags])
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...