等待 React 组件中的异步功能并显示 Spinner

Waiting for async function in React component & Showing Spinner

这里是初学者。

尝试从服务器获取一些数据,并在获取后将其显示在我的 React 组件中。 但是,我无法将异步函数集成到我的反应组件中。

import React, { useState } from "react";
import { request } from "graphql-request";

async function fetchData() {
  const endpoint = "https://localhost:3090/graphql"

  const query = `
    query getItems($id: ID) {
      item(id: $id) {
        title
      }
    }
  `;

  const variables = {
    id: "123123123"
  };

  const data = await request(endpoint, query, variables);
  // console.log(JSON.stringify(data, undefined, 2));

  return data;
}

const TestingGraphQL = () => {
  const data = fetchData().catch((error) => console.error(error));

  return (
    <div>
      {data.item.title}
    </div>
  );
};

export default TestingGraphQL;

我想在等待时简单地显示一个微调器或其他东西,但我试过了,似乎因为返回了一个承诺,我不能这样做。

这里您需要使用 useEffect 钩子来调用 API。 从 API 返回的 data,我在这里存储一个状态,以及一个 loading 状态以指示何时进行调用。

按照下面代码之间添加的注释进行操作 -

代码

import React, { useState, useEffect } from "react"; // importing useEffect here
import Layout from "@layouts/default";
import ContentContainer from "@components/ContentContainer";
import { request } from "graphql-request";

async function fetchData() {
   const endpoint = "https://localhost:3090/graphql"

   const query = `
     query getItems($id: ID) {
       item(id: $id) {
         title
       }
     }
   `;

   const variables = {
      id: "123123123"
   };

   const data = await request(endpoint, query, variables);
   // console.log(JSON.stringify(data, undefined, 2));

   return data;
}

const TestingGraphQL = () => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  
  // useEffect with an empty dependency array works the same way as componentDidMount
  useEffect(async () => {
     try {
       // set loading to true before calling API
       setLoading(true);
       const data = await fetchData();
       setData(data);
       // switch loading to false after fetch is complete
       setLoading(false);
     } catch (error) {
       // add error handling here
       setLoading(false);
       console.log(error);
     }
  }, []);

  // return a Spinner when loading is true
  if(loading) return (
    <span>Loading</span>
  );

  // data will be null when fetch call fails
  if (!data) return (
    <span>Data not available</span>
  );

  // when data is available, title is shown
  return (
    <Layout>
      {data.item.title}
    </Layout>
  );
};

因为 fetchData() returns 您需要在 TestingGraphQL 中处理它的承诺。我建议 onComponentMount 进行数据通话。将检索到的数据设置到 state var 中,以便在数据调用完成时作出反应以跟踪并重新呈现。

我添加了一个加载状态变量。如果加载为真,则显示 'loading' 否则显示数据。您可以稍后将它们更改为组件以满足您的需要。

参见下面的示例,从钩子切换到 class,但您应该能够让它工作! :)

class TestingGraphQL extends Component {
  constructor() {
    super();
    this.state = { data: {}, loading: true};
  }
  
  //when the component is added to the screen. fetch data
  componentDidMount() {
    fetchData()
      .then(json => { this.setState({ data: json, loading: false }) })
      .catch(error => console.error(error));
  }
  
  render() {
     return (
      {this.state.loading ? <div>Loading Spinner here</div> : <div>{this.state.data.item.title}</div>}
    );
  }
};