В нижней части каждой страницы сообщений моего сайта я хочу отобразить соответствующие сообщения на основе тегов текущих сообщений.Например, если у меня есть сообщение с тегом «собака», я хочу отобразить как 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])
}