繁体   English   中英

React如何从api获取大量数据

[英]React how to fetch a lot of data from an api

我有一个api,可为我提供一些要以最流畅的方式显示在屏幕上的数据。 我的想法是从api以异步方式获取数据,并在收到api的响应后立即渲染它。 这是我班

import React, { Component, Fragment } from "react";   
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import Episode from "../components/Episode";

import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
import CircularProgress from "@material-ui/core/CircularProgress";

const styles = theme => ({
  progress: {
    display: "flex",
    justifyContent: "center",
    alignItems: "center"
  },
  text: {
    marginTop: 20,
    marginLeft: 30
  }
});

class SeriesPage extends Component {
  constructor(props) {
    super(props);

    this.state = {
      apiToken: "",
      serie: null,
      episode: 1,
      episodes: [],
      endEpisode: 100
    };
  }

  async componentDidMount() {
    await this.getTokenFromApi();
    await this.getSerieDetailsByApiName();
    for(int i = 0; i< this.state.endEpisode; i++){
        this.getSerieEpisode();
    }
  }

  getTokenFromApi = async () => {
    const data = {
      name: "generateToken",
      param: {
        email: "-",
        pass: "-"
      }
    };
    return fetch("api", {
      method: "post",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json"
      },
      body: JSON.stringify(data)
    })
      .then(response => {
        if (!response.ok) {
          this.setState({
            episodes: "Network request failed"
          });
          throw Error("Network request failed");
        }
        return response;
      })
      .then(res => {
        return res.json();
      })
      .then(content => {
        if (content.response.status === 200) {
          this.setState({
            apiToken: content.response.result.token
          });
        }
      })
      .catch(error => {
        this.setState({
          episodes: "There was an internal error"
        });
        throw error;
      });
  };

  getSerieDetailsByApiName = async () => {
    const data = {
      name: "getSerieDetailsByApiName",
      param: {
        serieApiName: this.props.match.params.series
      }
    };
    return fetch("api", {
      method: "post",
      headers: {
        Authorization: "Bearer " + this.state.apiToken,
        "Content-Type": "application/json"
      },
      body: JSON.stringify(data)
    })
      .then(response => {
        if (!response.ok) {
          this.setState({
            episodes: "Network request failed"
          });
          throw Error("Network request failed");
        }
        return response;
      })
      .then(response => {
        return response.json(); //response.json() is resolving its promise. It waits for the body to load
      })
      .then(responseData => {
        if (responseData.response.status === 200) {
          this.setState({
            serie: responseData.response.result
          });
        }
      })
      .catch(error => {
        this.setState({
          episodes: "There was an internal error"
        });
        throw error;
      });
  };

  getSerieEpisode = async () => {
    const data = {
      name: "getEpisodeBySeriesApiName",
      param: {
        serieApiName: this.props.match.params.series,
        ep: this.state.episode
      }
    };
    console.log(data);
    return fetch("api", {
      method: "post",
      headers: {
        Authorization: "Bearer " + this.state.apiToken,
        "Content-Type": "application/json"
      },
      body: JSON.stringify(data)
    })
      .then(response => {
        if (!response.ok) {
          this.setState({
            episodes: "Network request failed"
          });
          throw Error("Network request failed");
        }
        return response;
      })
      .then(response => {
        return response.json(); //response.json() is resolving its promise. It waits for the body to load
      })
      .then(responseData => {
        console.log(responseData);
        if (responseData.response.status === 200) {
          this.setState(prevState => ({
            episodes: [...prevState.episodes, responseData.response.result]
          }));
        }
      })
      .catch(error => {
        this.setState({
          episodes: "There was an internal error"
        });
      });
  };

  render() {
    const { classes, theme } = this.props;
    var series =
      this.state.serie === "No results found" ? (
        <Typography
          className={classes.text}
          component="h2"
          variant="h5"
          color="error"
          gutterBottom
        >
          {this.state.serie}
        </Typography>
      ) : this.state.episodes === "There was an internal error" ? (
        <Typography
          className={classes.text}
          component="h2"
          variant="h5"
          color="error"
          gutterBottom
        >
          {this.state.episodes}
        </Typography>
      ) : (
        this.state.episodes.map((item, i) => {
          const { classes, headerIsHidden, ...other } = this.props;
          return <Episode key={i} episode={item} {...other} />;
        })
      );

    if (this.state.episodes) {
      return (
        <Fragment>
          <div className="series">
            <div className="container">
              <Grid container spacing={24}>
                {series}
                {this.state.loadingState ? (
                  <p className="loading"> loading More Items..</p>
                ) : (
                  ""
                )}
              </Grid>
            </div>
          </div>
        </Fragment>
      );
    } else {
      return (
        <Grid className={classes.progress} item xs={12}>
          <CircularProgress size={100} />
        </Grid>
      );
    }
  }
}
export default withStyles(styles, { withTheme: true })(SeriesPage);

基本上,此类会获取componentDidMount方法上的数据并为每个情节启动一个for循环,直到到达结尾为止,我觉得这不是更好的方法。

这种方法的问题在于componentDidMount和render可能需要一段时间才能执行,具体取决于情节数。

在我看来,可能平滑的方式来做到这一点的方法是是:1)使用虚拟化渲染情节data.So如果您有大量的记录只有什么是可见得到render.Take看看这个库HTTPS ://github.com/bvaughn/react-virtualized

2)使用按需方式仅获取用户可以看到的数据。您可以通过分页数据来实现此目的,以便在用户滚动记录时获取新页面。

您可以使用redux-saga,它提供了易于使用的内置函数,例如“ fork”,它充当侦听器并在后台启动获取过程。 也可以使用其他功能或称之为“效果”的功能。 它们非常易于使用,非常适合您的用例。 货叉示例

暂无
暂无

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

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