【问题标题】:GraphQL retrieve data for specific blocks - Gatsby + WordpressGraphQL 检索特定块的数据 - Gatsby + Wordpress
【发布时间】:2020-05-03 20:44:45
【问题描述】:

我有一个 React + Gatsby JS 项目,该项目通过其无头 API 从 Wordpress 站点检索数据。我是盖茨比的新手。

我网站上的每个页面都由块组成,而块又由字段组成。我正在使用 ACF 来构建这些。

我目前能够使用以下 GraphQL 查询检索每个页面和该页面中的块列表:

 query ($id: String!) {
        currentPage: wordpressPage(id: {eq: $id}) {
            title
            acf {
                page_blocks {
                 block_type {
                     acf_fc_layout
                 }
                }
            }
        }
    }

这将返回 ID 为 f4c4f4a7-ba0d-55b1-8877-16f543c22b80 的页面的以下数据

{
  "data": {
    "wordpressPage": {
      "id": "f4c4f4a7-ba0d-55b1-8877-16f543c22b80",
      "acf": {
        "page_blocks": [
          {
            "block_type": [
              {
                "acf_fc_layout": "page_title_and_text"
              },
              {
                "acf_fc_layout": "two_column_media_and_text"
              }
            ]
          }
        ]
      }
    }
  }
}

这些块在afc_fc_layout 旁边。 page_title_and_texttwo_column_media_and_text 都是该页面中的页面块。

现在,我认为下一步是为每个块制作一个 React 组件,将每个块的自定义字段数据传递给该组件。如果页面没有块,那么我就不需要检索该块的字段,对吗?

最初我以为我会从我的 React 组件运行另一个查询,请求该特定块的字段。但是我意识到我不能真正将变量(页面 ID)添加到我的组件中的静态查询中,每个 Gatsby docs,所以我将无法查询该特定页面的字段。如果我错了,请纠正我。

我相信我必须从我在这里向您展示的主要查询中检索我需要的那些字段,但是当并非所有页面都将要查询时,必须查询网站上每个可能的自定义字段似乎绝对是疯狂的有相同的块。

理想情况下会有某种语法,例如

...
acf {
    page_blocks {
        block_type {
            acf_fc_layout
            if (acf_fc_layout eq page_title_and_text) {
                title 
                text
            }

            if (acf_fc_layout eq two_column_media_and_text) {
                media
                text
            }
        }
    }
}
...

然后我会将这些字段传递给它们对应的 React 组件。

解决这个问题的正确方法是什么?

注意:我目前能够从 API 检索字段以呈现块。我更想知道我的 graphQL 查询是否可以为我过滤掉数据,或者是否有一种方法可以自定义 WP 端点以向我显示由页面上实际存在的块过滤的字段数据。

例如:站点在块 4、3、2、10、12、15.... 中查询数据,即使页面只有块 2。

我担心将来想要添加块的开发人员每次都必须重写查询,从而损害网站的可扩展性和潜在性能。

【问题讨论】:

    标签: graphql advanced-custom-fields gatsby wordpress-rest-api


    【解决方案1】:

    您说您是 Gatsby 的初学者,但您正在尝试做的事情涉及 Gatsby 内部的许多高级主题。我的回答很可能是不完整的,你需要自己弄清楚很多事情。

    准备好阅读大量文档并进行大量调试,以便与 Gatsby 一起工作。


    您想要programmatically create pages,具体取决于您的 GraphQL 查询结果。这意味着您需要创建一个页面范围的页面模板组件。

    在 Gatsby 项目的 templates 文件夹中,您创建一个模板,该模板以编程方式为您的每条路线选择正确的组件。要获取您的 ACF 数据,您可以使用 GraphQL page queries

    解决这个问题的正确方法是什么?

    另一种选择是:创建通过 props 检索数据的 React 组件。您无需为这些组件中的每一个提供自己的 GraphQL 查询,因为您已经在页面模板中进行了查询。

    acf: acf_fc_layout eq page_title_and_text -> React 组件PageTitleAndText.jsx

    const PageTitleAndText = ({ title, text}) => {
      return (
        <div>
          <h1>{title}</h1>
          <p>{text}</p>
        </div>
      );
    };
    
    // NO GraphQL query
    
    export default PageTitleAndText;
    

    相反,您将页面模板中的道具传递给您的组件:

    acfPageTemplate.jsx

    const acfPageTemplate = (props) => {
    
      return (
        <div>
          {/* pass props as data from the GraphQL query result here */}
            <PageTitleAndText title={props.data.currentPage.acf.page_blocks.block_type.acf_fc_layout.title  } 
                              text ={props.data.currentPage.acf.page_blocks.block_type.acf_fc_layout.text} />
    
        </div>
      );
    };
    export const query = graphql`
     query ($id: String!) {
            currentPage: wordpressPage(id: {eq: $id}) {
                title
                acf {
                    page_blocks {
                     block_type {
                         acf_fc_layout
                     }
                    }
                }
            }
        }
    `;
    
    export default acfPageTemplate;
    

    为每个 acf 布局定义一个页面模板。为每个布局选择正确的组件,并将 props 作为 GraphQL 查询结果中的数据传递。

    您需要将变量传递给您的页面查询。这样做的唯一方法是使用question 中描述的页面上下文:

    gatsby-node.js

    createPage({
      path: `/my-acf-page-title-and-text-page/`,
      component: path.resolve(`./src/templates/PageTitleAndText.jsx`),
      // The context is passed as props to the component as well
      // as into the component's GraphQL query.
      context: {
       id: acfFieldId, // pass the acf field id
     },
    })
    
    // define a createPage action for each of your acf layouts
    
    

    但我意识到,根据 Gatsby 文档,我无法真正将变量(页面 ID)添加到组件内的静态查询中,因此我无法查询该特定页面的字段。如果我错了,请纠正我。

    正确。这就是为什么你需要在gatsby-node.js中使用页面查询、页面模板和页面上下文变量的原因

    如果页面没有块,那么我就不需要检索该块的字段,对吧?

    是的。这就是您为每个 acf 布局创建不同页面模板的原因。您可以为所有布局创建一个大模板,但是您需要以编程方式决定要添加哪些组件。这超出了这个问题的范围。如果你想这样做,你应该问一个新问题。

    如果您决定这样做,我的建议是,在您进入下一个兔子洞之前,让它与一个特定的布局一起工作。

    【讨论】:

    • 感谢您非常彻底的回答。实际上,我确实遵循了所有说明。我正在使用 Gatsby-node.js 创建页面,使用页面模板来查询 API 并检索我的所有字段,现在我陷入了在该页面模板中呈现块的步骤。我试图实现的网站在页面之间没有一致性。所有页面都有不同顺序的不同块,所以我不能真正为每个布局制作一个页面模板。所以我的问题是更多,我如何有效地检索我的块信息而不必查询不在页面中的块。
    • 因此,例如,如果我的网站总共有 45 个块,每个块中都有一组自定义字段,那么每次加载页面模板时我是否真的需要查询这 45 个块中的每个字段,或者我可以根据该页面中实际存在的块进行查询吗?因此,如果一个页面有块 1、5 和 6,查询可以跳过其他的吗?还是我必须有可能有几百行长的查询?
    • Gatsby 在构建时“加载”一次模板。网站建成后,查询的复杂程度或效率都无关紧要。在此处了解构建过程:gatsbyjs.org/docs/overview-of-the-gatsby-build-process
    • 首先让模板按照我描述的方式只使用一个块。通过这种方式,您可以逐步接近解决方案。从那里您应该提出一个新问题,详细描述块如何引用字段,以及您如何需要有关跳过块等方面的帮助。
    • 拥有一个查询每个页面的每个可能的自定义字段(可能有数百个)的查询似乎很复杂,并且它不会使网站易于扩展。此外,我目前能够按您所说的显示一个块的字段。我不确定一个新问题会与这个不同。有人还建议我考虑在我的 Wordpress 端构建一个自定义端点,它只为我提供基于该页面的块的信息。我不知道该怎么做或者是否可能。
    猜你喜欢
    • 2020-11-02
    • 2021-04-14
    • 2022-01-02
    • 2020-09-24
    • 2020-09-03
    • 2017-01-19
    • 2017-10-17
    • 1970-01-01
    • 2019-07-19
    相关资源
    最近更新 更多