使用Gatsby处理URL参数

时间:2018-08-11 21:37:02

标签: reactjs gatsby

我正在使用React&Gatsby创建一个网站,并且已经按照我想要的方式进行了布局,我在理解如何使用URL Route参数来更改显示的内容时遇到了一些问题。

例如,假设我有一个页面categories.js可以监听http://website.com/categories,但是我希望能够动态处理任何URL参数,例如:

http://website.com/categories/animals

当像这样使用gatsby-link时:<Link to="/categories/animals" />它要我在Categories文件夹中创建一个名为animals.js的文件。相反,我希望category.js能够处理此页面的呈现,并根据URL参数中传递的类别选择适当的内容。

除了显示的项目外,该页面在所有类别中都是完全相同的,因此对于每个类别都拥有自己的静态页面并不有意义。

2 个答案:

答案 0 :(得分:2)

我认为您说错了

  

除了显示的项目外,该页面在所有类别中都是完全相同的,因此,每个类别都没有自己的静态页面是没有意义的。

实际上,这正是我发现 GatsbyJS 如此有用的地方,因为这是一个静态网站生成器

这意味着您可以为Gatsby提供一个template组件,该组件将为所有类别提供相同的布局,然后Gatsby将在构建时为您获取数据并创建静态页面 >。

  

Gatsby不仅限于使用像许多静态站点生成器这样的文件制作页面。通过Gatsby,您可以在构建时使用GraphQL查询数据并将数据映射到页面。 from Gatsby official tutorial

这个主意是这样的:

/gatsby-node.js中的

const path = require(`path`); // you will need it later to point at your template component

exports.createPages = ({ graphql, boundActionCreators }) => {
  const { createPage } = boundActionCreators;

  // we use a Promise to make sure the data are loaded
  // before attempting to create the pages with them
  return new Promise((resolve, reject) => {
    // fetch your data here, generally with graphQL.
    // for example, let say you use your data from Contentful using its associated source plugin
    graphql(`
      {
        allContentfulCategories {
          edges {
            node {
              id
              name
              description
              # etc...
            }
          }
        }
      }
    `).then(result => {
      // first check if there is no errors
      if (result.errors) {
        // reject Promise if error
        reject(result.errors);
      }

      // if no errors, you can map into the data and create your static pages
      result.data.allContentfulCategories.edges.forEach(({ node }) => {
        // create page according to the fetched data
        createPage({
          path: `/categories/${node.name}`, // your url -> /categories/animals
          component: path.resolve('./src/templates/categories.js'), // your template component
          context: {
            // optional,
            // data here will be passed as props to the component `this.props.pathContext`,
            // as well as to the graphql query as graphql arguments.
            id: node.id,
          },
        });
      });

      resolve();
    });
  });
};

然后您只需在模板组件上获取数据

在/src/templates/categories.js中的

import React from "react";

export default ({ data: { contentfulCategories: category } }) => {
  return (
    <div>
      <h1>{category.name}</h1>
      <div>{category.description}</div>
    </div>
  );
};

// we can query the needed category according to the id passed in the
// context property of createPage() in gatsby-node.js
export const query = graphql`
  query CategoryQuery($id: String!) {
    contentfulCategories(id: { eq: $id }) {
      name
      description
    }
  }
`;

如果您坚持动态呈现categories页,可以举this question的示例,该示例与您的示例相似,但是请注意,如果页面的在{strong> React 类组件的props生命周期方法中进行了componentWillReceiveProps的更改。

但是我真的不认为这是一个可靠的解决方案。

答案 1 :(得分:1)

编辑

经过永久搜索,我找到了更好的答案! -

https://github.com/gatsbyjs/gatsby/issues/13965#issuecomment-617364363

您认为您的案例示例如下:

gatsby-node.js

createPage({
    path: `/categories/:id`,
    matchPath: `/categories/:id`,
    component: path.resolve(`./src/pages/categories.js`),
})

categories.js

import React from "react"

export default function Booking({ id }) {
  return <div>categories #{id}</div>
}

旧答案

我似乎也遇到了完全相同的问题,也找不到任何答案。我的想法是也使用gatsby-node.js文件,但我不使用graphQL查询任何内容。

我的 /src/templates/categories.js 版本:

const path = require(`path`)

exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions
  createPage({
    path: `/categories/animals`,
    component: path.resolve(`./src/pages/categories.js`),
    // The context is passed as props to the component as well
    // as into the component's GraphQL query.
    context: {
      id: `animals`, //use this context parameter to do the dynamic stuff in your page
    },
  })
}

我希望这是有用的。