[英]Calling a function recursively in reactjs
I am calling an API recursively using axios in React.我在 React 中使用 axios 递归调用 API。 But it is not giving desired result.
但它没有给出预期的结果。 Here is the snippet:
这是片段:
callApi =(index)=> {
console.log('index data : ',this.props.modalData[index]);
let modalData = this.props.modalData
if(index < this.props.modalData.length-1){
const options ={
method: 'post',
data: this.props.modalData[index],
json: true,
url: config.api.root+'/sp/tms/tgbTripRefUpdate',
"headers": {'Authorization': localStorage.getItem('authHeader')},
}
axios(options).then(res=>{
modalData[index].Status='Success';
let display = [...this.state.displayModalData]
display.push(modalData[index])
this.setState({
"displayModalData" : [...display],
change : !this.state.change
},this.callApi(index+1))
}).catch(err=>{
modalData[index].Status='Failure';
let display = [...this.state.displayModalData]
display.push(modalData[index])
this.setState({
"displayModalData" : [...display],
change : !this.state.change
},this.callApi(index+1))
});
}
else{
this.setState({
showCloseBtn: true
})
}
}
The function callApi
gets called many times.函数
callApi
被多次调用。 Unable to understand why.无法理解为什么。
You're using the callback of setState
in a bad way, it should be () => this.callApi(index + 1)
:您正在以一种糟糕的方式使用
setState
的回调,它应该是() => this.callApi(index + 1)
:
callApi = index => {
if(index > this.props.modalData.length) return;
console.log("index data : ", this.props.modalData[index]);
let modalData = this.props.modalData;
if (index < this.props.modalData.length - 1) {
const options = {
method: "post",
data: this.props.modalData[index],
json: true,
url: config.api.root + "/sp/tms/tgbTripRefUpdate",
headers: { Authorization: localStorage.getItem("authHeader") }
};
axios(options)
.then(res => {
modalData[index].Status = "Success";
let display = [...this.state.displayModalData];
display.push(modalData[index]);
this.setState(
{
displayModalData: [...display],
change: !this.state.change
},
() => this.callApi(index + 1) // here
);
})
.catch(err => {
modalData[index].Status = "Failure";
let display = [...this.state.displayModalData];
display.push(modalData[index]);
this.setState(
{
displayModalData: [...display],
change: !this.state.change
},
() => this.callApi(index + 1) // here
);
});
} else {
this.setState({
showCloseBtn: true
});
}
};
Here are two approaches:这里有两种方法:
Working example (this example includes GET
requests to a public API, but just swap in your POST
requests; in addition, this example includes both options above this.fetchData
(option 1) and this.fetchDataRecursively
(option 2)):工作示例(此示例包括对公共 API 的
GET
请求,但只是交换您的POST
请求;此外,此示例包括this.fetchData
(选项 1)和this.fetchDataRecursively
(选项 2)之上的两个选项):
App.js应用程序.js
import React, { Component } from "react";
import app from "./axiosConfig";
import Spinner from "./Spinner";
import "./styles.css";
class App extends Component {
state = {
data: [],
showCloseButton: false,
isLoading: true,
err: ""
};
/* executed when component is mounted */
componentDidMount() {
// this.fetchData();
this.fetchDataRecursively();
}
/* loops through modalData as one unit and retrieves data */
fetchData = async () => {
const { modalData } = this.props;
try {
for (const index of modalData) {
/*
using a custom axios config found in "./axiosConfig"
to fetch data by modalData index with a predefined "baseURL"
*/
const res = await app.get(`/${index}`);
/*
the code below is not needed;
it's just there to add some time between each call
*/
await new Promise(res => setTimeout(() => res(), 1000));
/* using setState function to get prevState and adding new data to it */
this.setState(prevState => ({
data: [...prevState.data, res.data]
}));
}
/* once the loop above is done, sets isLoading to false */
this.setState({ isLoading: false });
} catch (err) {
/* if any of the fetches fail, the next calls won't be executed and the error is set to state */
this.setState({ err, isLoading: false });
}
};
/* rescursively loops failData as individual units and retrieves data */
fetchDataRecursively = async (index = 0) => {
const { failData } = this.props;
if (failData[index] !== undefined) {
try {
/*
using a custom axios config found in "./axiosConfig"
to fetch data by modalData index with a predefined "baseURL"
*/
const res = await app.get(`/${failData[index]}`);
/*
the code below is not needed;
it's just there to add some time between each call
*/
await new Promise(res => setTimeout(() => res(), 1000));
/* using setState function to get prevState and adding new data to it */
this.setState(prevState => ({
data: [...prevState.data, res.data]
}));
this.fetchDataRecursively(index + 1);
} catch (err) {
/* if any of the fetches fail, add to state */
this.setState(
prevState => ({
data: [
...prevState.data,
{ index: `Failed to fetch ${index}`, reason: err }
]
}),
() => this.fetchDataRecursively(index + 1)
);
}
} else {
this.setState({ isLoading: false });
}
};
/* mimics a modal toggle */
toggleModalButton = () =>
this.setState(prevState => ({
showCloseButton: !prevState.showCloseButton
}));
/*
The below is rendered according to state:
If "isLoading" is true: show Spinner
if "isLoading" is false but "err" is true: show err
Else: initially show the data and a button
data button toggles the data visibility
*/
render = () => (
<div style={{ width: 600, margin: "0 auto" }}>
{this.state.isLoading ? (
<Spinner />
) : this.state.err ? (
<p>{this.state.error}</p>
) : (
<div>
{!this.state.showCloseButton && (
<pre
style={{
background: "#ebebeb",
overflowY: "auto"
}}
>
<code>{JSON.stringify(this.state.data, null, 4)}</code>
</pre>
)}
<button onClick={this.toggleModalButton}>
{!this.state.showCloseButton ? "Close" : "Open"} Modal
</button>
</div>
)}
</div>
);
}
export default App;
axiosConfig.js axiosConfig.js
import get from "lodash.get";
import axios from "axios";
// const { baseURL } = process.env;
const baseURL = "https://jsonplaceholder.typicode.com/todos";
const app = axios.create({
baseURL
});
app.interceptors.response.use(
response => response,
error => {
const err = get(error, ["response", "data", "err"]);
return Promise.reject(err || error.message);
}
);
export default app;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.