在Gatsby-React类组件中使用Graphql获取数据

时间:2019-11-28 19:40:54

标签: reactjs graphql gatsby

这是Gatsby-React中的类组件,其中包含可以正常工作的硬编码数据:

import React from "react";

class ExmpClassComp extends React.Component {
  constructor(props) {
    super(props);
    this.clickHandler = this.clickHandler.bind(this);

    // hard-coded data:
    this.state = {
      myData: [
        {
          itemID: 1,
          name: "Isaac Newton",
          bio: [
            'Sir Isaac Newton PRS (25 December 1642 – 20 March 1726/27) was an English mathematician, physicist, astronomer, theologian, and author (described in his own day as a "natural philosopher") who is widely recognised as one of the most influential scientists of all time, and a key figure in the scientific revolution. His book Philosophiæ Naturalis Principia Mathematica (Mathematical Principles of Natural Philosophy), first published in 1687, laid the foundations of classical mechanics. Newton also made seminal contributions to optics, and shares credit with Gottfried Wilhelm Leibniz for developing the infinitesimal calculus.'
          ]
        },
        {
          itemID: 2,
          name: "Nikola Tesla",
          bio: [
            "Nikola Tesla (10 July 1856 – 7 January 1943) was one of the few greatest physicists ever - most likely the greatest one of all times.",
            "Tesla's work was systematically obstructed by Thomas Edison.",
            "American scientific community decided to decorate the great physicists Nikola Tesla with the award that on itself had the name of the person who truly envied Tesla and who could hardly be considered a scientist at all - IEEE Edison Medal."
          ]
        },
        {
          itemID: 3,
          name: "Albert Einstein",
          bio: [
            'Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc^2, which has been dubbed "the world\'s most famous equation". He received the 1921 Nobel Prize in Physics "for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect", a pivotal step in the development of quantum theory.'
          ]
        }
      ],
      currentDetails: {
        title: "Select a name in the sidebar list to learn more.",
        body: []
      }
    };
  }

  clickHandler(ev) {
    let listItems = ev.target.parentNode.children;
    for (let item of listItems) {
      if (item.hasAttribute("id")) {
        item.removeAttribute("id");
      }
    }
    ev.target.setAttribute("id", "clickedItem");

    for (let singleObj of this.state.myData) {
      if (ev.target.textContent === singleObj.name) {
        this.setState({
          currentDetails: {
            title: singleObj.name,
            body: singleObj.bio
          }
        });
      }
    }
  }

  render() {
    return (
      <div className="app-data">
        <ul>
          {this.state.myData.map((item, index) => {
            return (
              <li onClick={this.clickHandler} key={index}>
                {item.name}
              </li>
            );
          })}
        </ul>
        <div className="bio">
          <h3>{this.state.currentDetails.title}</h3>
          {this.state.currentDetails.body.map((item, index) => {
            return <p key={index}>{item}</p>;
          })}
        </div>
      </div>
    );
  }
}

export default ExmpClassComp;

但是,当我想使用Graphql来获取数据时:

import React from "react";
import { useStaticQuery, graphql } from "gatsby";

class ExmpClassComp extends React.Component {
  constructor(props) {
    super(props);
    this.clickHandler = this.clickHandler.bind(this);

    this.state = {
      myData: useStaticQuery(graphql`
        query MyAppQueryList {
          file(relativePath: { eq: "appData.json" }) {
            childrenAppDataJson {
              name
              bio
            }
          }
        }
      `),
      currentDetails: {
        title: "Select a name in the list to learn more.",
        body: []
      }
    };
  }

  clickHandler(ev) {
    let listItems = ev.target.parentNode.children;
    for (let item of listItems) {
      if (item.hasAttribute("id")) {
        item.removeAttribute("id");
      }
    }
    ev.target.setAttribute("id", "clickedItem");

    for (let singleObj of this.state.myData) {
      if (ev.target.textContent === singleObj.name) {
        this.setState({
          currentDetails: {
            title: singleObj.name,
            body: singleObj.bio
          }
        });
      }
    }
  }

  render() {
    return (
      <div className="app-data">
        <ul>
          {this.state.myData.map((item, index) => {
            return (
              <li onClick={this.clickHandler} key={index}>
                {item.name}
              </li>
            );
          })}
        </ul>
        <div className="bio">
          <h3>{this.state.currentDetails.title}</h3>
          {this.state.currentDetails.body.map((item, index) => {
            return <p key={index}>{item}</p>;
          })}
        </div>
      </div>
    );
  }
}

export default ExmpClassComp;

我收到此错误消息:

错误:无效的挂钩调用。挂钩只能在功能组件的主体内部调用。发生这种情况可能是由于以下原因之一:

  1. 您可能使用的React和渲染器版本不匹配(例如React DOM)
  2. 您可能正在违反挂钩规则
  3. 您可能在同一应用中拥有多个React副本

请问可以帮忙吗?谢谢!

2 个答案:

答案 0 :(得分:0)

useStaticQuerycustom-hook,因此只能在功能组件中调用。

  

Gatsby v2.1.0引入了useStaticQuery,这是一种新的Gatsby功能,提供了在构建时使用 React Hook 来查询GraphQL的功能。

在gatsby中,要获取具有类组件的静态查询(如您的情况),您需要使用StaticQuery

import React from "react"
import { StaticQuery, graphql } from "gatsby"
import PropTypes from "prop-types"

const Header = ({ data }) => (
  <header>
    <h1>{data.site.siteMetadata.title}</h1>
  </header>
)

class App extends Component {
  render() {
    return (
      <StaticQuery
        query={graphql`
          query {
            site {
              siteMetadata {
                title
              }
            }
          }
        `}
        render={data => <Header data={data} {...props} />}
      />
    );
  }
}

此外,您可能希望使用page query它将数据注入组件props。

答案 1 :(得分:0)

最后,我将类更改为功能组件,导入了{useState},它的工作方式如下:

import React from "react";
import { useStaticQuery, graphql } from "gatsby";
import { useState } from "react";

function DemoAppList() {
  const fetchedData = useStaticQuery(graphql`
    query MyAppQueryList {
      file(relativePath: { eq: "appData.json" }) {
        childrenAppDataJson {
          name
          bio
        }
      }
    }
  `);

  const dataArr = fetchedData.file.childrenAppDataJson;

  const [currentContent, setContent] = useState({
    title: "Select a name in the sidebar list to learn more.",
    body: []
  });

  const clickHandler = ev => {
    let listItems = ev.target.parentNode.children;
    for (let item of listItems) {
      if (item.hasAttribute("id")) {
        item.removeAttribute("id");
      }
    }
    ev.target.setAttribute("id", "clickedItem");

    for (let singleObj of dataArr) {
      if (ev.target.textContent === singleObj.name) {
        setContent({
          title: singleObj.name,
          body: singleObj.bio
        });
      }
    }
  };

  return (
    <div className="app-data">
      <ul>
        {dataArr.map((item, index) => {
          return (
            <li onClick={clickHandler} key={index}>
              {item.name}
            </li>
          );
        })}
      </ul>
      <div className="bio">
        <h3>{currentContent.title}</h3>
        {currentContent.body.map((item, index) => {
          return <p key={index}>{item}</p>;
        })}
      </div>
    </div>
  );
}
export default DemoAppList;