盖茨比动态弹头

Gatsby dynamic slug

首先我要展示我的代码,然后解释问题:

我的 gatsby-node.js:

上有这个
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions
  if (node.internal.type === `ContetnfulPost`) {
    const slug = createFilePath({ node, getNode, basePath: `pages` })
    createNodeField({
      node,
      name: `slug`,
      value: slug,
    })
  }
}
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const result = await graphql(`
    query {
      allContentfulPost {
        edges {
          node {
            postTitle
            slug
          }
        }
      }
    }
  `)

  const posts = result.data.allContentfulPost.edges

  posts.forEach(({ node }, index) => {
    createPage({
      path: `${node.slug}`,
      component: path.resolve(`./src/templates/blogPost.js`),
      context: {
        slug: node.slug,
        prev: index === 0 ? null : posts[index - 1].node,
        next: index === posts.length - 1 ? null : posts[index + 1].node,
      },
    })
  })
}

然后我在两个地方查询博客 posts:一个是这样的博客页面:

blog.js 页数:

function Blog() {
  return (
    <Layout>
      <SEO title="Blog Page" />
      <StaticQuery
        query={graphql`
          query blogQuery {
            allContentfulPost {
              edges {
                node {
                  slug
                  postTitle
                  postImage {
                    file {
                      url
                      fileName
                    }
                  }
                  postContent {
                    postContent
                  }
                  postDate
                }
              }
            }
          }
        `}
        render={data => (
          <ul>
            {data.allContentfulPost.edges.map(({ node }) => {
              return (
                <BlogPostsContainer>
                  <Link to={`${node.slug}`}>
                    <BlogPostImage src={node.postImage.file.url} />
                    <PostTitle>{node.postTitle}</PostTitle>
                  </Link>
                </BlogPostsContainer>
              )
            })}
          </ul>
        )}
      />
    </Layout>
  )
}

还有一个 React 组件,我用它在主页上显示我的一些 post:

BlogSection.js

function BlogSection() {
  return (
    <BlogSectionWrapper>
      <StaticQuery
        query={graphql`
          query homeBlogQuery {
            allContentfulPost(limit: 2) {
              edges {
                node {
                  slug
                  postTitle
                  postImage {
                    file {
                      url
                      fileName
                    }
                  }
                  postContent {
                    postContent
                  }
                  postDate
                }
              }
            }
          }
        `}
        render={data => (
          <ul>
            {data.allContentfulPost.edges.map(({ node }) => {
              return (
                <HomePostsContainer>
                  <Link to={`${node.slug}`}>
                    <HomePostImage src={node.postImage.file.url} />
                    <PostTitle>{node.postTitle}</PostTitle>
                  </Link>
                </HomePostsContainer>
              )
            })}
          </ul>
        )}
      />
      <ButtonWrapper></ButtonWrapper>
      <FlatButton
        item={{
          title: "See all posts",
          icon: "/images/icons/book.svg",
          link: "/blog",
        }}
      />
    </BlogSectionWrapper>
  )
}

现在的问题是,当我从主页(从 BlogSection.js 组件呈现的那些)单击博客 post 时,URL 通常是 http://localhost:8000/test-post.

但是当我从博客页面(从 blog.js 文件呈现)单击 post 时,URL 变为 http://localhost:8000/blog/test-post

我还在每个 post 上添加了 PrevNext 按钮,当我点击它们时,它只是将 slug 添加到 URL,例如当我在http://localhost:8000/test-post点击Next,变成了http://localhost:8000/test-post/test-post2

我怎样才能让 URL 只显示 post slug 或为所有 post 加上一个 /blog 前缀独立于我点击的地方是吗?

我在 gatsby-node.js 文件上试过了,但它不起作用:

posts.forEach(({ node }, index) => {
    createPage({
      path: `/blog/${node.slug}`, //<===== THIS LINE
      component: path.resolve(`./src/templates/blogPost.js`),
      context: {
        slug: node.slug,
        prev: index === 0 ? null : posts[index - 1].node,
        next: index === posts.length - 1 ? null : posts[index + 1].node,
      },
    })
  })

您的动态 post 是在 localhost:8000/:post-slug 而不是在 /blog/:post-slug 下创建的,因为:

  path: `${node.slug}`,

因此,第一步是添加以下内容(您目前已尝试过的内容):

posts.forEach(({ node }, index) => {
    createPage({
      path: `/blog/${node.slug}`, 
      component: path.resolve(`./src/templates/blogPost.js`),
      context: {
        slug: node.slug,
        prev: index === 0 ? null : posts[index - 1].node,
        next: index === posts.length - 1 ? null : posts[index + 1].node,
      },
    })
  })

之后,请记住,所有未以 / 为前缀的链接都将连接到当前的 URL,就像标准锚点 (<a>标签)。只需在 slug 的开头添加一个 / 就可以解决问题。这解释了这个问题:

I also added Prev and Next buttons on each post and when I click on them, it just appends the slug in the URL, for instance when I'm on http://localhost:8000/test-post and click Next, it becomes http://localhost:8000/test-post/test-post2.

现在,例如,如果您想从主页转到特定 post,您需要将 /blog 添加到 URL,因为它不是post 子弹的一部分:

function BlogSection() {
  return (
    <BlogSectionWrapper>
      <StaticQuery
        query={graphql`
          query homeBlogQuery {
            allContentfulPost(limit: 2) {
              edges {
                node {
                  slug
                  postTitle
                  postImage {
                    file {
                      url
                      fileName
                    }
                  }
                  postContent {
                    postContent
                  }
                  postDate
                }
              }
            }
          }
        `}
        render={data => (
          <ul>
            {data.allContentfulPost.edges.map(({ node }) => {
              return (
                <HomePostsContainer>
                  <Link to={`/blog/${node.slug}`}>
                    <HomePostImage src={node.postImage.file.url} />
                    <PostTitle>{node.postTitle}</PostTitle>
                  </Link>
                </HomePostsContainer>
              )
            })}
          </ul>
        )}
      />
      <ButtonWrapper></ButtonWrapper>
      <FlatButton
        item={{
          title: "See all posts",
          icon: "/images/icons/book.svg",
          link: "/blog",
        }}
      />
    </BlogSectionWrapper>
  )
}

注意 <Link to={`/blog/${node.slug}`}>。并用 blog.js 模板做同样的事情。

之前的行为在 blog.js 中有效,因为路径不是相对的,它将 post slug 连接到当前的 URL (/blog),但不是't 指向 /blog.

要解决进一步的问题,请检查所有 slug 并添加 /(如果需要)以避免连接问题。

总结:

  • gatsby-node.js 中的 /blog/:post-slug 下创建动态 posts:这将生成 /blog
  • 下的所有 posts
  • 将所有链接指向 /blog/:post-slug,无论来源如何 URL(主页指向 post,等等)。
  • 在所有指向 post 的链接的开头添加斜杠 (/) 以避免 URL 问题的串联和相关性。相同的解决方法适用于下一个和上一个按钮。