[英]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.