【问题标题】:Bringing in multiple loaders in a single page: React JS在单个页面中引入多个加载器:React JS
【发布时间】:2020-02-07 00:32:50
【问题描述】:

我正在尝试实现一个仪表板,其中我有几个需要显示的项目。在下面的示例中,我有 4 个矩形框(实际上是 4 个不同的图表)和一个表格。我将 react-table 用于数据网格,将语义 ui-react 表用于微调器目的。

现在的问题是,这些都是相互独立的。我使用 settimeout 模拟了数据,就好像它来自后端一样。我所需要的只是单独的加载器,只要数据到达,它就应该被隐藏起来。我已将加载器提取为一个单独的组件,以便它充当所有项目的通用加载器。

通常,如果存在,API 会给我一个项目数组,如果不是一个空数组。出于模拟目的,我使用了 setTimeout

可以为每个项目设置单独的标志,但这似乎不是一个好方法。

模拟沙盒:https://codesandbox.io/s/react-table-row-table-vdnfh

App.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"));

【问题讨论】:

    标签: javascript reactjs ecmascript-6 promise ecmascript-5


    【解决方案1】:

    当使用绝对定位元素import { Dimmer } from "semantic-ui-react",并且不希望整个页面有4个重叠元素时,你需要给它们一个相对定位的父元素,例如:

    .box {
      position: relative;
    }
    

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


    如果需要区分空卡,API为空卡返回"",则初始状态需要与该值不同,例如:

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

    然后检查该初始值:

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

    【讨论】:

    • 您正在使用 import { Dimmer } from "semantic-ui-react" 和以下 CSS:display: absolute; top: 0 !important; left: 0 !important; => 显示 4 个覆盖整个页面的重叠对话框。我更新了答案以将position: relative 添加到调光器的父级或某些祖先,例如.box
    • 没有错。 &lt;div&gt;{[1, 2, 3]}&lt;/div&gt; 将数组转换为字符串123。如果 API 返回一个数组,你可能想做一些.map()...
    • 防范未定义:this.props.data &amp;&amp; this.props.data.map(...)
    • 我会将其标记为正确答案。还有一件事,我如何实现这一点: Spinner 应该出现,直到响应到达并且如果它的空显示“未找到”。尝试过这样的事情:codesandbox.io/s/react-table-row-table-vdnfh inside index.tsx for card 4 data
    • index.tsx 内,您必须防止未定义:cardData4 &amp;&amp; cardData4.length,但这不会在加载时显示元素。您必须在 Card.tsx 中移动逻辑,例如this.props.data &amp;&amp; this.props.data.length ? this.props.data.map(...) : 'Not found'
    【解决方案2】:

    我不完全确定您要解决的问题是什么;您的代码沙箱显示逐卡到达的数据,我认为这就是您想要的。随着每次超时的解决,状态会发生变化,组件会重新渲染,并且会出现新到达的数据。

    但是,我看到您将相同的 this.state.spinnerFlag 传递到所有卡片中。相反,您可以根据数据的可用性来计算微调器状态。

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

    然后微调器将准确显示,直到该卡的数据可用为止。

    【讨论】:

    • 如果没有数据怎么办;像加载器将永远显示?
    • 等待数据和空卡需要使用不同的值(例如undefined vs ""
    • 我创建了一个答案来举例说明如果 API 为空卡返回 ""。如果它为空卡返回其他内容,那么这个答案已经可以正常工作了。
    猜你喜欢
    • 2012-12-03
    • 2023-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-28
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    相关资源
    最近更新 更多