#javascript #reactjs #graphql #gatsby #slug
#javascript #reactjs #graphql #gatsby #slug
Вопрос:
Мой gatsby slug не генерирует правильный URL страницы. Он должен генерировать -> / second-post-getting-started
Но он генерирует -> / second-post-getting-started / второй после начала работы
Это добавление слага на текущую страницу вместо того, чтобы возвращаться назад и затем добавлять. Я перепроверил gatsby-node.js и другие страницы, но не может найти ошибку.
Вот gatsby-node.js код.
const path = require('path')
const { slugify } = require('./src/util/utilityFunctions')
const authors = require('./src/util/authors')
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'),
tag: path.resolve('src/templates/tag-posts.js'),
tagsPage: path.resolve('src/templates/tags-page.js'),
authorPosts: path.resolve('src/templates/author-posts.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,
// Find author imageUrl from author array and pass it to template
imageUrl: authors.find(x => x.name === node.frontmatter.author)
.imageUrl,
},
})
})
// Create posts pagination pages
const postsPerPage = 2
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,
},
})
})
// Get all tags
let tags = []
_.each(posts, edge => {
if (_.get(edge, 'node.frontmatter.tags')) {
tags = tags.concat(edge.node.frontmatter.tags)
}
})
let tagPostCounts = {} // { tutorial: 2, design: 1}
tags.forEach(tag => {
// Or 0 cause it might not exist yet
tagPostCounts[tag] = (tagPostCounts[tag] || 0) 1
})
// Remove duplicates
tags = _.uniq(tags)
// Tags page (all tags)
createPage({
path: '/tags',
component: templates.tagsPage,
context: {
tags,
tagPostCounts,
},
})
// Tag posts pages
tags.forEach(tag => {
createPage({
path: `/tag/${_.kebabCase(tag)}`,
component: templates.tag,
context: {
tag,
},
})
})
// Create author posts pages
authors.forEach(author => {
createPage({
path: `/author/${slugify(author.name)}`,
component: templates.authorPosts,
context: {
authorName: author.name,
imageUrl: author.imageUrl,
},
})
})
}
index.js код
import React from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { graphql, StaticQuery } from "gatsby"
import Post from "../components/Post"
import PaginationLinks from '../components/PaginationLinks'
const IndexPage = () => {
const postPerPage = 2
let numberOfPages
return(
<Layout pageTitle = "Full Stack Me"
pageSubtitle = "Just an Encyclopedia for Web Devs" >
<SEO title="Home" keywords={[`gatsby`, `application`, `react`]} />
<StaticQuery
query={indexQuery} render={data => {
numberOfPages = Math.ceil(data.allMarkdownRemark.totalCount / postPerPage)
return(
<div>
{data.allMarkdownRemark.edges.map(({ node }) => (
<Post
key={node.id }
title={node.frontmatter.title}
author={node.frontmatter.author}
slug={node.fields.slug}
date={node.frontmatter.date}
body={node.excerpt}
fluid={node.frontmatter.images.childImageSharp.fluid}
tags={node.frontmatter.tags}
/>
))}
<PaginationLinks currentPage={1} numberOfPages={numberOfPages}/>
</div>
)
}}
/>
</Layout>
)
}
const indexQuery = graphql`
query{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
limit: 2
) {
totalCount
edges{
node{
id
frontmatter{
title
date(formatString: "MMM Do YYYY")
author
tags
images{
childImageSharp{
fluid(maxWidth: 600){
...GatsbyImageSharpFluid
}
}
}
}
fields{
slug
}
excerpt
}
}
}
}
`
export default IndexPage
Комментарии:
1. Вы уверены, что вы просто не ссылаетесь на неправильный путь (например,
foo
вместо/foo
) в вашем HTML / JSX?2. Где я могу получить этот файл. Если вы хотите взглянуть, вот ссылка на репозиторий git
Ответ №1:
Вы ссылаетесь на, {slug}
когда slug
перед ним не стоит косая черта:
<Link to={slug}>{/* No slash at the beginning */}
<Img className="card-image-top" fluid={fluid} />
</Link>
(источник)
Это делает его URL-адресом, относящимся к пути. Если вы просматриваете страницу по адресу /foo/
и ссылаетесь на href="bar"
, полный URL-адрес будет /foo/bar
. Вы почти наверняка хотите использовать абсолютные пути, но имя хоста относительное, URL-адреса, что вы можете сделать, убедившись, что вы всегда начинаете URL-адрес с косой черты:
<Link to={`/${slug}/`}>{/* With starting and trailing slashes */}
<Img className="card-image-top" fluid={fluid} />
</Link>