Всем привет.
С помощью gatsby-node.js генерирую страницы для постов и для отдельной страницы, где выводятся все теги из постов.
Код gatsby-node.js
const path = require('path');
const _ = require('lodash');
exports.createPages = async ({ actions, graphql, reporter }) => {
const { createPage } = actions;
const blogPostTemplate = path.resolve('./src/templates/post.js');
const tagTemplate = path.resolve('./src/templates/tags.js');
const result = await graphql(`
{
postsRemark: allMdx(sort: { order: DESC, fields: [frontmatter___date] }, limit: 2000) {
edges {
node {
slug
frontmatter {
tags
}
}
}
}
tagsGroup: allMdx(limit: 2000) {
group(field: frontmatter___tags) {
fieldValue
}
}
}
`);
// handle errors
if (result.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`);
return;
}
const posts = result.data.postsRemark.edges;
// Create post detail pages
posts.forEach(({ node }) => {
createPage({
path: node.slug,
component: blogPostTemplate,
});
});
// Extract tag data from query
const tags = result.data.tagsGroup.group;
// Make tag pages
tags.forEach((tag) => {
createPage({
path: `/tags/${_.kebabCase(tag.fieldValue)}/`,
component: tagTemplate,
context: {
tag: tag.fieldValue,
},
});
});
};
Код post.js — шаблон для отображения страницы
import React from 'react';
import { Link, graphql } from 'gatsby';
import { MDXRenderer } from 'gatsby-plugin-mdx';
import Layout from '../components/Layout';
import Seo from '../components/seo';
import * as post from '../components/BlogPost.module.scss';
function BlogPost({ data }) {
return (
<Layout>
<Seo title={data.mdx.frontmatter.title} />
<main className={`${post.container} ${post.body}`}>
<article>
<h2 className={post.title}>{data.mdx.frontmatter.title}</h2>
<p className={post.category}>
Опубликован <span>{data.mdx.frontmatter.date}</span>
<br />
Рубрика:{' '}
<span>
{data.mdx.frontmatter.tags.map((tag) => {
return (
<Link to={`/${tag}`} className={post.categoryLink}>
{tag}
</Link>
);
})}
</span>
</p>
<MDXRenderer>{data.mdx.body}</MDXRenderer>
</article>
</main>
</Layout>
);
}
export const PostQuery = graphql`
query ($id: String) {
mdx(id: { eq: $id }) {
frontmatter {
title
tags
date(formatString: "DD.MM.YYYY")
}
body
id
}
}
`;
export default BlogPost;
Шаблон для отображения страницы тегов
import React from 'react';
import PropTypes from 'prop-types';
// Components
import { Link, graphql } from 'gatsby';
const Tags = ({ pageContext, data }) => {
const { tag } = pageContext;
const { edges, totalCount } = data.allMdx;
const tagHeader = `${totalCount} post${totalCount === 1 ? '' : 's'} tagged with "${tag}"`;
return (
<div>
<h1>{tagHeader}</h1>
<ul>
{edges.map(({ node }) => {
const { slug } = node;
const { title } = node.frontmatter;
return (
<li key={slug}>
<Link to={slug}>{title}</Link>
</li>
);
})}
</ul>
{/*
This links to a page that does not yet exist.
You'll come back to it!
*/}
<Link to="/tags">All tags</Link>
</div>
);
};
Tags.propTypes = {
pageContext: PropTypes.shape({
tag: PropTypes.string.isRequired,
}),
data: PropTypes.shape({
allMdx: PropTypes.shape({
totalCount: PropTypes.number.isRequired,
edges: PropTypes.arrayOf(
PropTypes.shape({
node: PropTypes.shape({
frontmatter: PropTypes.shape({
title: PropTypes.string.isRequired,
}),
fields: PropTypes.shape({
slug: PropTypes.string.isRequired,
}),
}),
}).isRequired,
),
}),
}),
};
export default Tags;
export const pageQuery = graphql`
query ($tag: String) {
allMdx(
limit: 2000
sort: { fields: [frontmatter___date], order: DESC }
filter: { frontmatter: { tags: { in: [$tag] } } }
) {
totalCount
edges {
node {
slug
frontmatter {
title
}
}
}
}
}
`;
Проблема: когда на странице тегов я докликиваю до списка постов конкретного тега (например, /tags/tag_1/ — показывает все посты с тегом tag_1) — я кликаю на любой пост (открывается адрес /tags/tag_1/post_name), но Гэтсби показывает ошибку, как будто для страницы нет шаблона (отображается 404).
А если открыть /post_name — то шаблон подтягивается норм и пост отображается.
Что я делаю не так, подскажите, пожалуйста :(