Reputation: 359
How to clear an array and immediately populate with react using hooks (useState)
const [log, setLog] = useState([]);
const onSubmit = data => {
let num = parseInt(data.num);
setLog([]);
for (let i = 1; i <= num; i++) {
axios
.get(data.url)
.then(function(response) {
setLog([...log, { type: "ok", message: "Good" }]);
})
.catch(function(error) {
setLog([...log, { type: "error", message: "Bad" }]);
});
}
};
In this code, setLog([])
fails to clean the array because is asynchronous. How can I handle this? Thanks in advance.
Edit: I am creating a request log to a URL and save the request result. It can be 1 attempt or many attempts and I must record all the responses. Each time I press the submit button, the log must be cleaned and the requests started again.
Upvotes: 1
Views: 4277
Reputation: 749
I think this will work:
const [log, setLog] = useState([]);
const onSubmit = data => {
let num = parseInt(data.num);
for (let i = 1; i <= num; i++) {
axios
.get(data.url)
.then(function(response) {
setLog([{ type: "ok", message: "Good" }]);
})
.catch(function(error) {
setLog([{ type: "error", message: "Bad" }]);
});
}
};
Upvotes: 0
Reputation: 468
Unpopular opinion:
Use class component. It provides accessor to the current state.
class SomeComponent extends Component {
state = {
isSubmitting: false,
logs: []
}
async submit(data){
const num = data.num;
if (this.isSubmitting) {
return;
}
let logs = [];
this.setState({ logs, isSubmitting: true });
for (const i = 0; i < num; i++) {
await axios.get(data.url)
.then(() => {
logs = logs.concat({ type: "ok", message: "Good" });
this.setState({ logs });
})
.catch(() => {
logs = logs.concat({ type: "error", message: "Bad" })
this.setState({ logs })
})
}
this.setState({ isSubmitting: false });
}
render(){
return (
<form onSubmit={() => this.submit(getSomeData())}></form>
)
}
}
// use this if you want the request to be executed parallely
async submit(data){
const num = data.num;
if (this.isSubmitting) {
return;
}
let logs = [];
this.setState({ logs, isSubmitting: true });
const requests = []
for (const i = 0; i < num; i++) {
requests.push(
axios.get(data.url)
.then(() => {
logs = logs.concat({ type: "ok", message: "Good" });
this.setState({ logs });
})
.catch(() => {
logs = logs.concat({ type: "error", message: "Bad" })
this.setState({ logs })
})
)
}
await Promise.all(requests)
this.setState({ isSubmitting: false });
}
Upvotes: 1
Reputation: 1696
why do you want to do setLog([])
and then setLog([...log, ]);
?
If you want to setLog
without previous log
content just do:
const [log, setLog] = useState([]);
const onSubmit = data => {
let num = parseInt(data.num);
for (let i = 1; i <= num; i++) {
axios
.get(data.url)
.then(function(response) {
setLog([{ type: "ok", message: "Good" }]);
})
.catch(function(error) {
setLog([{ type: "error", message: "Bad" }]);
});
}
};
edit: Ok I think I understood what you need. I am not sure but try the following
const [log, setLog] = useState([]);
const onSubmit = data => {
let num = parseInt(data.num);
setLog([]);
for (let i = 1; i <= num; i++) {
axios
.get(data.url)
.then(function(response) {
setState(prevLog => {
prevLog.push({ type: "ok", message: "Good" });
return {prevLog};
});
})
.catch(function(error) {
setState(prevLog => {
prevLog.push({ type: "error", message: "Bad" });
return {prevLog};
});
});
}
};
Upvotes: 1