简体   繁体   English

在单个页面中引入多个加载器:React JS

[英]Bringing in multiple loaders in a single page: React JS

I am trying to implement a dashboard where in I have couple of items that needs to be shown.我正在尝试实现一个仪表板,其中有几个需要显示的项目。 In the following example I have 4 rectangular boxes(In actual those are 4 different graphs) and a table.在下面的示例中,我有 4 个矩形框(实际上是 4 个不同的图表)和一个表格。 I am using react-table for the data grid purposes and a semantic-ui-react table for the spinner purposes.我将 react-table 用于数据网格目的,将语义 ui-react 表用于微调器目的。

Now the issue is, these all are independent of each other.现在的问题是,这些都是相互独立的。 I have mocked the data using a settimeout as if it were coming from the back-end.我使用 settimeout 模拟了数据,就好像它来自后端一样。 All I need is individual loaders and it should be hidden whenever data arrives.我所需要的只是单独的加载器,只要数据到达,它就应该被隐藏起来。 I have extracted the loader as a separate component, so that it behaves as a common loader for all the items.我已将加载器提取为一个单独的组件,以便它充当所有项目的通用加载器。

Usually the API would give me array of items if present, and if not an empty array.通常 API 会给我项目数组(如果存在),如果不是空数组。 For mock purposes, I have used setTimeout出于模拟目的,我使用了 setTimeout

Could go for individual flags for each item, but that does not seems a good approach. go 是否可以为每个项目提供单独的标志,但这似乎不是一个好方法。

Mock Sandbox: https://codesandbox.io/s/react-table-row-table-vdnfh模拟沙箱: https://codesandbox.io/s/react-table-row-table-vdnfh

App.tsx应用程序.tsx

import * as React from "react";
import { render } from "react-dom";
import "./styles.css";
import Card from "./Card";

interface IProps {}

interface IState {
  cardData1: any;
  cardData2: any;
  cardData3: any;
  cardData4: any;
}

class App extends React.Component<IProps, IState> {
  constructor(props: any) {
    super(props);
    this.state = {
      cardData1: undefined,
      cardData2: undefined,
      cardData3: undefined,
      cardData4: undefined
    };
  }

  componentDidMount() {
    this.getGraphData();
  }

  // the reason why I call this four times is because, in my case the API is same for all the graphs, only an attribute changes so just mocking it here
  getGraphData = () => {
    this.setGraphData("graph1");
    this.setGraphData("graph2");
    this.setGraphData("graph3");
    this.setGraphData("graph4");
  };

  setGraphData = (cardNumber: string) => {
    //based on the attribute I set the corresponding card data
    if (cardNumber === "graph1") {
      setTimeout(() => {
        this.setState({ cardData1: [1, 2, 3] });
      }, 1000);
    }
    if (cardNumber === "graph2") {
      setTimeout(() => {
        this.setState({ cardData2: [3, 4, 5] });
      }, 2000);
    }

    if (cardNumber === "graph3") {
      setTimeout(() => {
        this.setState({ cardData3: [6, 7, 8] });
      }, 3000);
    }
    if (cardNumber === "graph4") {
      setTimeout(() => {
        this.setState({ cardData4: [] });
      }, 4000);
    }
  };

  render() {
    let { cardData1, cardData2, cardData3, cardData4 } = this.state;
    return (
      <>
        <Card
          name="Card1"
          data={this.state.cardData1}
          spinnerFlag={cardData1 === undefined}
        />
        <Card
          name="Card3"
          data={this.state.cardData2}
          spinnerFlag={cardData2 === undefined}
        />
        <Card
          name="Card3"
          data={this.state.cardData3}
          spinnerFlag={cardData3 === undefined}
        />
        <Card
          name="Card3"
          data={this.state.cardData4}
          spinnerFlag={cardData4 === undefined}
        />
      </>
    );
  }
}

render(<App />, document.getElementById("root"));

I'm not entirely sure what the problem you're trying to solve is;我不完全确定您要解决的问题是什么; your code sandbox shows the data arriving card-by-card, which I think is what you're going for.您的代码沙箱显示逐卡到达的数据,我认为这就是您想要的。 As each timeout resolves, the state changes, the component re-renders, and the newly arrived data appears.随着每个超时的解决,state 发生变化,组件重新渲染,并且新到达的数据出现。

However, I see that you're passing the same this.state.spinnerFlag into all the cards.但是,我看到您将相同的this.state.spinnerFlag传递到所有卡片中。 Instead you can calculate the spinner state based on the availability of the data.相反,您可以根据数据的可用性计算微调器 state。

<Card
  name="Card1"
  data={this.state.cardData1}
  spinnerFlag={this.state.cardData1 === ""}
/>

Then the spinner will show exactly until the data for that card is available.然后微调器将准确显示,直到该卡的数据可用。

When using the absolutely positioned element import { Dimmer } from "semantic-ui-react" , and do not wish to have 4 overlapping elements over the whole page, you need to give them a relatively positions parent, eg:当使用绝对定位元素import { Dimmer } from "semantic-ui-react" ,并且不希望在整个页面上有 4 个重叠元素时,您需要给它们一个相对位置的父元素,例如:

.box {
  position: relative;
}

https://codesandbox.io/s/react-table-row-table-et7ie https://codesandbox.io/s/react-table-row-table-et7ie


If you need to distinguish between empty card and the API returns "" for an empty card, then the initial state needs to be different from that value, eg:如果需要区分空卡和API为空卡返回"" ,则初始的state需要与该值不同,例如:

this.state = {
  cardData1: undefined,
  cardData2: undefined,
  cardData3: undefined,
  cardData4: undefined
};

and then check for that initial value:然后检查该初始值:

<Card
  name="Card1"
  data={this.state.cardData1}
  spinnerFlag={this.state.cardData1 === undefined}
/>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM