Reputation: 250
I am using a simple form with a text input. When something is written the state of the component is updated, and as this.setState
is asynchronous, I fetch the data from the API on componentDidUpdate
.
The problem is that I don't find the solution to avoid the infinite loop, as I update the state after using axios:
constructor(props) {
super(props);
this.state = {
searchValue: "",
data: null,
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
this.setState({ searchValue: event.target.value });
}
componentDidUpdate() {
const url = 'https://www.google.com/?search=' + this.state.searchValue;
axios.get(url).then(response => this.setState({data: response.data}));
}
Upvotes: 2
Views: 3048
Reputation: 4877
Since you want to fetch new data on input change, you can make the call directly in handleInputChange
callback.
handleInputChange({target: {value}}) {
this.setState({ searchValue: value });
this.fetchData(value);
}
fetchData(text) {
const url = 'https://www.google.com/?search=' + text;
axios.get(url).then(({data}) => this.setState({data}));
}
Now, if you want to use componentDidUpdate
you can compare previousState
with your state.
handleInputChange({target: {value}}) {
this.setState({ searchValue: value });
}
fetchData(text) {
const url = 'https://www.google.com/?search=' + text;
axios.get(url).then(({data}) => this.setState({data}));
}
componentDidUpdate(prevProps, prevState) {
// only update if searchValue has changed
if (prevState.searchValue !== this.state.searchValue) {
this.fetchData(this.state.searchValue);
}
}
Also with hooks:
const [searchValue, setSearchValue] = useState('');
const [data, setData] = useState(null);
function handleInputChange({target: {value}}) {
setSearchValue(value);
}
function fetchData(text) {
const url = 'https://www.google.com/?search=' + text;
axios.get(url).then(({data}) => setData({data}));
}
useEffect(() => {
// don't run on componentDidMount or if string is empty
if (searchValue) {
fetchData(searchValue);
}
}, [searchValue]);
Update 2021
The above implementations work fine, but there is a slightly better way to handle the request inside useEffect
:
const [searchValue, setSearchValue] = useState('');
const [data, setData] = useState(null);
function handleInputChange({target: {value}}) {
setSearchValue(value);
}
useEffect(() => {
async function fetchData(text) {
try {
// don't run on componentDidMount or if string is empty
if (text) {
return
}
const url = `https://www.google.com/?search=${text}`;
const { data } = await axios.get(url);
setData({ data });
} catch(e) {
// handle error
}
};
fetchData(searchValue);
}, [searchValue]);
Upvotes: 9