【问题标题】:Trying to add a list of posts to my homepage instead of a separate page in Gatsby using Contentful尝试使用 Contentful 将帖子列表添加到我的主页而不是 Gatsby 中的单独页面
【发布时间】:2021-10-06 00:30:21
【问题描述】:

我希望在我的主页上放置一个帖子列表,而不是创建一个单独的动态页面。这是我的gatsby-node.js 文件

// DYNAMICALLY CREATE PAGES FOR EACH POST
module.exports.createPages = async ({ graphql, actions, reporter }) => {
  const { createPage } = actions;
  const postTemplate = path.resolve('src/templates/news.js');
  const postResult = await graphql(`
    query {
      allContentfulPost {
        edges {
          node {
            slug
          }
        }
      }
    }
  `);

  // Handle errors
  if (postResult.errors) {
    reporter.panicOnBuild('Error while running GraphQL query.');
    return;
  }

  // Create the pages for each markdown file
  postResult.data.allContentfulPost.edges.forEach(({ node }) => {
    createPage({
      component: postTemplate,
      path: `/news/${node.slug}`,
      context: {
        slug: node.slug,
      },
    });
  });

  // PAGINATION FOR BLOG POSTS
  const postsResult = await graphql(`
    {
      allContentfulPost(sort: { fields: date, order: DESC }, limit: 1000) {
        edges {
          node {
            slug
          }
        }
      }
    }
  `);

  if (postsResult.errors) {
    reporter.panicOnBuild('Error while running GraphQL query.');
    return;
  }

  // Create blog-list pages
  const posts = postsResult.data.allContentfulPost.edges;
  const postsPerPage = 12;
  const postNumPages = Math.ceil(posts.length / postsPerPage);
  Array.from({ length: postNumPages }).forEach((_, i) => {
    createPage({
      path: i === 0 ? '/' : `/news/${i + 1}`,
      component: path.resolve('./src/templates/news-list.js'),
      context: {
        limit: postsPerPage,
        skip: i * postsPerPage,
        postNumPages,
        currentPage: i + 1,
      },
    });
  });
};

这是我的news-list.js 文件

import React from 'react';
import { Link, graphql } from 'gatsby';

import Layout from '../components/layout';
import SEO from '../components/seo';

export const query = graphql`
  query ($skip: Int!, $limit: Int!) {
    allContentfulPost(sort: { fields: date, order: DESC }, limit: $limit, skip: $skip) {
      edges {
        node {
          title
          slug
          date(formatString: "MMMM Do, YYYY")
        }
      }
    }
  }
`;

const NewList = (props) => {
  // const { postNumPages } = props.pageContext;

  const posts = props.data.allContentfulPost.edges;

  return (
    <Layout>
      <SEO title='News' />

      {posts.map(({ node }) => {
        const title = node.title || node.slug;
        return (
          <div className='container mx-auto prose prose-lg'>
            <div className='mb-2'>
              <Link to={`/posts/${node.slug}`}>
                <h3 className='underline font-sans mb-1'>{title}</h3>
              </Link>

              <div className='flex items-center justify-between'>
                <span className='font-mono text-sm'>{node.date}</span>
              </div>
            </div>
          </div>
        );
      })}
    </Layout>
  );
};

export default NewList;

我尝试将上述news-list.js 作为组件从我的模板文件夹导入到我的index.js 文件夹中。但是我得到了错误:

TypeError: Cannot read property 'allContentfulPost' of undefined

但如果我将 path: i === 0 ? '/news' : /news/${i + 1}, 添加到我的节点文件中并转到 localhost/news 我会得到帖子列表。

但我希望它们出现在主页上.. 所以我想如果我只拥有/ 它会起作用的结果不是。

我怎样才能让LH/news 列出的帖子显示在我的主页上。

更新

最新答案后的新组件

import React from 'react';
import { useStaticQuery, graphql, Link } from 'gatsby';

import Layout from '../components/layout';

// import News from '../components/news';
// import NewsList from '../templates/news-list';

export const query = graphql`
  {
    allContentfulPost(sort: { fields: date, order: DESC }, limit: 1000) {
      edges {
        node {
          title
          slug
          date(formatString: "MMMM Do, YYYY")
        }
      }
    }
  }
`;

const Index = ({ data }) => {
  const { site } = useStaticQuery(
    graphql`
      query {
        site {
          siteMetadata {
            companyname
          }
        }
      }
    `
  );

  return (
    <Layout>
      <section className='c-mt-10'>
        <div className=''>
          <div className='font-mono md:flex md:justify-between'>
            <div className='mb-5'>
              <a href={`mailto:hello@${site.siteMetadata.companyname}.co.uk`}>
                hello@pfb{site.siteMetadata.companyname}.co.uk
              </a>
              <br />
              <br />
              <tel>+44 020 3925 6054</tel>
            </div>

            <a
              href='https://www.google.com/maps/place/Warnford+Court,+29+Throgmorton+St,+London+EC2N+2AT/@51.5154096,-0.0890419,17z/data=!3m1!4b1!4m5!3m4!1s0x48761cacb440b98d:0x9742679143333ff!8m2!3d51.5154096!4d-0.0868479'
              target='_blank'
              rel='noreferrer'>
              <address className='text-right'>
                Warnford Court
                <br />
                29 Throgmorton Street
                <br /> London, EC2N 2AT
              </address>
            </a>
          </div>
        </div>

        <div>
          <h2>Company News</h2>
          <ul>
            {data.allContentfulPost.edges.map(({ node }) => (
              <li key={node.title}>
                <Link to={node.slug}>{node.title}</Link>
              </li>
            ))}
          </ul>
        </div>
      </section>
    </Layout>
  );
};
export default Index;

【问题讨论】:

  • news-list.js 是 Gatsby 页面组件吗(即它是否存在于 pages 文件夹中)?
  • 不,这存在于模板目录中

标签: javascript node.js reactjs graphql gatsby


【解决方案1】:

我认为你混合了很多概念。

一件事是gatsby-node.js 查询,可用于基于参数(在您的情况下为slug)基于动态数据(在您的情况下来自 Contentful CMS)创建动态页面。

另一件事是page queries,一种在顶级组件(页面或模板,而不是组件)中检索数据的方法。

如果你想在你的主页上列出你的所有帖子,你只需要创建一个 GraphQL 查询并循环遍历结果,就像这样:

const IndexPage = ({ data }) => {

   return <Layout> 
    <ul>
    {data.allContentfulPost.edges.map(({node})=> <li key={node.title}><Link to={node.slug}>{title}</Link></li>)}
    </ul>
   </Layout>

}

export const query = graphql`
    {
      allContentfulPost(sort: { fields: date, order: DESC }, limit: 1000) {
        edges {
          node {
            title
            slug
            date(formatString: "MMMM Do, YYYY")
          }
        }
      }
    }
`;

使用页面查询时,您的数据存储在props.data 中,因此您可以将它们直接解构为data

在您的情况下,您是在页面中导入模板,这没有多大意义,因为您没有查询等。

【讨论】:

  • 这是有道理的,我在您的更新中添加了一个新组件,但仍然收到相同的错误:(
  • 正如我所说,页面查询仅在顶级组件(页面)中可用。它不能是一个孤立的组件,它必须在主页本身。如果你复制粘贴 sn-p,应该单独工作。
  • 完美的工作......我现在可以重建它周围的索引页面
  • @mrpbennett 您可以在常规旧组件中使用StaticQuery,查看文档:gatsbyjs.com/docs/how-to/querying-data/use-static-query
  • 当然可以,但对我来说,在这种情况下(从概念上)这不是静态查询的目的。它们的行为与页面查询略有不同,并且以不同的方式重新水合(它们在每次渲染中被触发)组件。但你是对的,这是另一种获取数据的方式
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多