【问题标题】:Gatsby dynamic slug盖茨比动态 slug
【发布时间】:2021-07-12 13:51:04
【问题描述】:

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

我的 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,
      },
    })
  })
}

然后我在 2 个地方查询博客文章:一个像这样的博客页面:

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>
  )
}

另一个是我用来在主页上显示我的一些帖子的反应组件:

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 组件呈现的)点击博客文章时,URL 通常是http://localhost:8000/test-post

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

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

如何保留 URL 以仅显示帖子 slug 或者可能为所有帖子添加 /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,
      },
    })
  })

【问题讨论】:

    标签: javascript reactjs graphql gatsby contentful


    【解决方案1】:

    您的动态帖子是在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,就像标准锚点(&lt;a&gt; 标记)一样。只需在 slug 的开头添加 / 就可以了。这就解释了这个问题:

    我还在每个帖子上添加了 Prev 和 Next 按钮,当我点击 他们,它只是在 URL 中附加 slug,例如当我在 http://localhost:8000/test-post 然后点击下一步,就变成了 http://localhost:8000/test-post/test-post2.

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

    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>
      )
    }
    

    注意&lt;Link to={`/blog/${node.slug}`}&gt;。对blog.js 模板执行相同的操作。

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

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

    总结:

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

    【讨论】:

    • 感谢@Ferran,它工作正常。所以如果我想从 Contentful 添加另一个内容模型,比如说 Portfolio,我是否必须复制 gatsby-node.js 中的代码并查询投资组合架构?或者还有另一个代码更少的技巧?
    • 您将需要使用多个查询实例。检查stackoverflow.com/a/64594951/5585371
    • 你能检查一下这个也请:stackoverflow.com/questions/67248328/…
    猜你喜欢
    • 1970-01-01
    • 2022-01-25
    • 2020-10-16
    • 2019-08-07
    • 2019-08-23
    • 2021-12-14
    • 2022-08-19
    • 2021-07-30
    • 2020-12-02
    相关资源
    最近更新 更多