【问题标题】:GatsbyJS getting data from Restful APIGatsbyJS 从 Restful API 获取数据
【发布时间】:2018-08-24 06:08:04
【问题描述】:

我是 React 和 GatsbyJS 的新手。我很困惑,无法以一种简单的方式从第三方 Restful API 加载数据。

例如,我想从 randomuser.me/API 获取数据,然后能够在页面中使用这些数据。

让我们这样说:

  import React from 'react'
  import Link from 'gatsby-link'

  class User extends React.Component {
    constructor(){
      super();
      this.state = {
        pictures:[],
      };

    }

    componentDidMount(){
      fetch('https://randomuser.me/api/?results=500')
      .then(results=>{
        return results.json();
      })
      .then(data=>{
        let pictures = data.results.map((pic,i)=>{
            return(
              <div key={i} >
                <img key={i} src={pic.picture.medium}/>
              </div>
            )
        })
        this.setState({pictures:pictures})
      })
    }

    render() {
      return (<div>{this.state.pictures}</div>)
    }
  }

  export default User;

但我想得到 GraphQL 的帮助,以便对用户进行过滤和排序等...... ..

您能帮我找到如何获取数据并将它们插入到gatsby-node.js GraphQL 的示例吗?

【问题讨论】:

  • 你不能在运行时使用 GatsbyJS 的 GraphQL 接口,只能在构建时使用。但是,如果你真的需要 GraphQL,你可以使用第三方库。
  • 感谢您的 PM。但我不打算制作运行时 GraphQL,为了更好的解释,我检查了这个例子 github.com/gatsbyjs/gatsby/tree/master/examples/… 。 ,但这只是从内容定制到特定 API,我想构建一个类似的示例来从任何 Restful API 加载数据。我检查了 GatsbyJS 插件部分,有插件 'gatsby-source-api' 但我无法使其工作或在我的示例应用程序中运行
  • 这些插件和示例旨在在构建时使用(不是在componentDidMount() 上,不是在fetch 上,我不确定我是否清楚地解释自己)。恐怕目前没有用于自定义 REST API 调用的通用插件。

标签: reactjs rest gatsby


【解决方案1】:

您可以在前端使用 react useEffect 从 API 获取数据。它完美运行,您将不再在构建时看到任何错误

 const [starsCount, setStarsCount] = useState(0)
  useEffect(() => {
    // get data from GitHub api
    fetch(`https://api.github.com/repos/gatsbyjs/gatsby`)
      .then(response => response.json()) // parse JSON from request
      .then(resultData => {
        setStarsCount(resultData.stargazers_count)
      }) // set data for the number of stars
  }, [])

【讨论】:

    【解决方案2】:

    如果你想使用 GraphQL 来获取你的数据,你必须创建一个sourceNode。关于creating a source plugin 的文档可以帮助你。

    按照这些步骤可以在您的 Gatsby 项目中使用 GraphQL 查询 randomuser 数据。

    1) 在 gatsby-node.js 中创建节点

    在您的根项目文件夹中,将此代码添加到gatsby-node.js

    const axios = require('axios');
    const crypto = require('crypto');
    
    exports.sourceNodes = async ({ actions }) => {
      const { createNode } = actions;
    
      // fetch raw data from the randomuser api
      const fetchRandomUser = () => axios.get(`https://randomuser.me/api/?results=500`);
      // await for results
      const res = await fetchRandomUser();
    
      // map into these results and create nodes
      res.data.results.map((user, i) => {
        // Create your node object
        const userNode = {
          // Required fields
          id: `${i}`,
          parent: `__SOURCE__`,
          internal: {
            type: `RandomUser`, // name of the graphQL query --> allRandomUser {}
            // contentDigest will be added just after
            // but it is required
          },
          children: [],
    
          // Other fields that you want to query with graphQl
          gender: user.gender,
          name: {
            title: user.name.title,
            first: user.name.first,
            last: user.name.last,
          },
          picture: {
            large: user.picture.large,
            medium: user.picture.medium,
            thumbnail: user.picture.thumbnail,
          }
          // etc...
        }
    
        // Get content digest of node. (Required field)
        const contentDigest = crypto
          .createHash(`md5`)
          .update(JSON.stringify(userNode))
          .digest(`hex`);
        // add it to userNode
        userNode.internal.contentDigest = contentDigest;
    
        // Create node with the gatsby createNode() API
        createNode(userNode);
      });
    
      return;
    }
    

    我使用axios 获取数据,因此您需要安装它:npm install --save axios

    说明:

    目标是为您要使用的每条数据创建每个节点。 根据createNode documentation,您必须提供一个包含少量必填字段(id、parent、internal、children)的对象。

    从 randomuser API 获取结果数据后,您只需创建此节点对象并将其传递给 createNode() 函数。

    在这里,我们映射到您想要获得 500 个随机用户 https://randomuser.me/api/?results=500 的结果。

    使用必填字段和所需字段创建userNode 对象。 您可以根据要在应用中使用的数据添加更多字段。

    只需使用 Gatsby API 的 createNode() 函数创建节点即可。

    2) 使用 GraphQL 查询您的数据

    完成此操作后,运行 gatsby develop 并转到 http://localhost:8000/___graphql

    您可以使用 GraphQL 来创建完美的查询。由于我们将节点对象的internal.type 命名为'RandomUser',我们可以查询allRandomUser 来获取我们的数据。

    {
      allRandomUser {
        edges {
          node {
            gender
            name {
              title
              first
              last
            }
            picture {
              large
              medium
              thumbnail
            }
          }
        }
      }
    }
    

    3) 在您的 Gatsby 页面中使用此查询

    在您的页面中,例如src/pages/index.js,使用查询并显示您的数据:

    import React from 'react'
    import Link from 'gatsby-link'
    
    const IndexPage = (props) => {
      const users = props.data.allRandomUser.edges;
    
      return (
        <div>
          {users.map((user, i) => {
            const userData = user.node;
            return (
              <div key={i}>
                <p>Name: {userData.name.first}</p>
                <img src={userData.picture.medium} />
              </div>
            )
          })}
        </div>
      );
    };
    
    export default IndexPage
    
    export const query = graphql`
      query RandomUserQuery {
        allRandomUser {
          edges {
            node {
              gender
              name {
                title
                first
                last
              }
              picture {
                large
                medium
                thumbnail
              }
            }
          }
        }
      }
    `;
    

    就是这样!

    【讨论】:

    • 如果我想从我的个人数据库中获取数据怎么办?我的意思是,在生产中部署应用程序我不能在 gatsby-node.js 文件中留下 url https://randomuser.me/api...它应该与设置的服务器(例如 Express)连接。我尝试在 package.json 中添加与服务器地址匹配的代理,但它不起作用
    • @Enrico 我会说您应该首先检查是否有 gatsby 插件可用于连接到您的数据库。否则,您可以使用 Express 创建自己的 REST api,例如 app.get("/api-url", (req, res, next) =&gt; { /*get data*/ res.json(data) })。然后你就可以在 gatsby-node.js 文件中使用你的 api url:https://myapp.com/api-url.
    • @AidanGrimshaw 据我所知,gatsby-node.js 仅在 build 时执行。所以答案是否定的,这不会在运行时更新
    • 这将是一个很棒的 Gatsby 教程,谢谢!
    • 有人可以在 2020 年更新这个吗?我试过了,但不再支持加密 npmjs.com/package/crypto
    【解决方案3】:

    上面给出的答案有效,除了第 2 步中的查询似乎只为我返回一个节点。我可以通过将 totalCount 添加为边的兄弟来返回所有节点。 IE。

    {
      allRandomUser {
        totalCount
        edges {
          node {
            id
            gender
            name {
              first
              last
            }
          }
        }
      }
    }
    

    【讨论】:

      【解决方案4】:

      对此接受的答案效果很好,只是要注意,如果您使用boundActionCreators,则会出现弃用警告。必须将其重命名为 actions 以避免出现此警告。

      【讨论】:

      • 嗨@pixelbreaker - 将来,这可能会更好地作为对答案的评论,而不是答案。
      • 完全同意@Slabgorb,但仍然是+1,因为这是一个好点:) 你介意对@pixelbreaker 接受的答案发表评论吗?甚至建议修改?
      【解决方案5】:

      非常感谢,这对我来说很好,我只更改了 gastbyjs-node.js 的一小部分,因为它在使用同步和等待时出错,我想我需要更改构建过程的某些部分才能使用 babel允许我使用同步或等待。

      这是对我有用的代码。

       const axios = require('axios');
       const crypto = require('crypto');
      
       // exports.sourceNodes = async ({ boundActionCreators }) => {
       exports.sourceNodes = ({boundActionCreators}) => {
      const {createNode} = boundActionCreators;
      return new Promise((resolve, reject) => {
      
      // fetch raw data from the randomuser api
      // const fetchRandomUser = () => axios.get(`https://randomuser.me/api/?results=500`);
      // await for results
      // const res = await fetchRandomUser();
      
      axios.get(`https://randomuser.me/api/?results=500`).then(res => {
      
        // map into these results and create nodes
        res.data.results.map((user, i) => {
      
          // Create your node object
          const userNode = {
            // Required fields
            id: `${i}`,
            parent: `__SOURCE__`,
            internal: {
              type: `RandomUser`, // name of the graphQL query --> allRandomUser {}
              // contentDigest will be added just after
              // but it is required
            },
            children: [],
      
            // Other fields that you want to query with graphQl
            gender: user.gender,
            name: {
              title: user.name.title,
              first: user.name.first,
              last: user.name.last
            },
            picture: {
              large: user.picture.large,
              medium: user.picture.medium,
              thumbnail: user.picture.thumbnail
            }
            // etc...
          }
      
          // Get content digest of node. (Required field)
          const contentDigest = crypto.createHash(`md5`).update(JSON.stringify(userNode)).digest(`hex`);
          // add it to userNode
          userNode.internal.contentDigest = contentDigest;
      
          // Create node with the gatsby createNode() API
          createNode(userNode);
        });
        resolve();
      });
      
      });
      
      }
      

      【讨论】:

      • 由于节点的构建是在页面加载之前完成的(毕竟这是一个静态站点生成器),您不必担心 babel。只需确保您用于开发的节点版本以及您部署到的服务上的节点版本(Netlify?)都支持异步/等待
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      • 2021-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      相关资源
      最近更新 更多