Reputation: 125
I'm trying to fetch data from a public API with Axios, and display what I get through a React app. But I can't find a condition in my componentDidUpdate() to make it render only once, when the user modifies input. Anyone'd have an idea ?
Here's my code :
import React, { Component } from 'react';
import axios from "axios";
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
input: "",
output: []
}
}
componentDidUpdate() {
axios.get(`https://geo.api.gouv.fr/communes?nom=${this.state.input}`)
.then(response => {
this.setState((prevState) => {
if (prevState.input !== this.state.input) {
return { output: response.data };
}
});
})
.catch(function (error) {
console.log(error);
})
}
handleInput = (event, input) => {
this.setState({input: event.target.value});
}
render() {
return (
<React.Fragment>
<label>Recherche : <input type="text" onChange={this.handleInput} /></label>
<div>
{this.state.output.map((value, index) => <p key={index}>{value.nom}</p>)}
</div>
</React.Fragment>
);
}
}
export default App;
Thanks for helping.
Upvotes: 7
Views: 7881
Reputation: 281764
Assuming you need to take an action everytime your state change, you need to check if the state has updated before triggering an action
in componentDidUpdate
otherwise API call will be made whenever your component updates.
If you only wish to call the API once, then call it in componentDidMount
componentDidUpdate(prevProps, prevState) {
if(prevState.input !== this.state.input) {
axios.get(`https://geo.api.gouv.fr/communes?nom=${this.state.input}`)
.then(response => {
this.setState({ output: response.data });
})
.catch(function (error) {
console.log(error);
})
}
}
Upvotes: 3
Reputation: 125
Assuming you need to take an action everytime your state change...
Actually, this is what I wanted to do, and the solution I've found is to wrap the Axios request in a
if(prevState.input !== this.state.input) { --- }
condition, just as Shubham told me to do. Nevertheless, I had to remove the setState() inner condition to make it work.
Thanks to everyone !
Upvotes: 0
Reputation: 4008
The only moment when you want to get data, is when your input has changed. Why not use the method to trigger the fetch? The state is used to keep track of what is entered and retrieved, but you should not rely on the state change to trigger function dependent on user changes.
See your example transposed to what I think is a good example, with my comments: https://codesandbox.io/s/oxoxoym85y
Upvotes: 0
Reputation: 29
If you need to call the API once You can use componentWillMount, once the state changed when the data arrives your component will rerender
Only if you want to use your API anytime the component rerender you can use componentDidUpdate, in this case make sure you are not changing the state to avoid infinite loop.
Upvotes: 0
Reputation: 6280
You are looping in your code: after your component is updated, componentDidUpdate
will be invoked; inside this function you are calling setState
which will re-render the component. This will trigger componentDidUpdate
another time and so on...
I think you should just move your API call from componentDidUpdate
to componentDidMount
.
Upvotes: 1