Reputation: 49
I have a parent component called DeviceTab.js
and a child component called Graph.js
. The child component receives two props: name
and span
. I need to make api calls in Graph.js
that are dependent on the initial name
or span
props and when they get updated from the parent. Right now, I make the api call in componentDidMount()
shown below. However when the props get updated (and the states that I have for these two props also get updated), the api doesn't get called. I think it's because componentDidMount()
gets only called once. Should I use another lifecycle method and/or move the api call somewhere else?
In Graph.js
I convert these two props to states as such:
componentWillReceiveProps(props) {
this.setState({ device: props.device })
this.setState({ span: props.span })
}
These two props are used as parameters in an api function call in componentDidMount()
in my child component as such:
componentDidMount(){
const {name, span} = this.state
fetch('https://devices-api.com/name=${name}&span=${span}')
.then((response) => response.json())
.catch((error) => console.error("Error: ", error))
.then((data) => {
this.setState({ devices : data });
});
}
When the parent props for name
and span
get updated in the parent component, I use componentDidUpdate()
in the child component to update the child's name and span states as such:
componentDidUpdate(prevProps) {
if (this.props.name !== prevProps.name) {
this.setState({
name: this.props.name,
});
}
if (this.props.span !== prevProps.span) {
this.setState({
span: this.props.span,
});
}
}
EDIT:
I took @ Harmandeep Singh Kalsi 's advice and move the api call into componentDidUpdate
but am still having issues with loading my data. Here's the updated method:
componentDidUpdate(prevProps){
if (this.props.name !== prevProps.name) {
this.setState({ name: this.props.name})
// your api call goes here
const {name, span} = this.state
fetch('https://devices-api.com/name=${name}&span=${span}')
.then((response) => response.json())
.catch((error) => console.error("Error: ", error))
.then((data) => {
this.setState({ devices : data });
});
}
}
if (this.props.span !== prevProps.span) {
this.setState({ span: this.props.span})
// your api call goes here
const {name, span} = this.state
fetch('https://devices-api.com/name=${name}&span=${span}')
.then((response) => response.json())
.catch((error) => console.error("Error: ", error))
.then((data) => {
this.setState({ devices : data });
});
}
}
}
When I console.log
the api url, I am seeing an infinite # of calls using the initial prop values passed from the parent i.e. https://devices-api.com/name=test1&span=2
. When updated prop values are passed from the parent, there is another set of infinite api calls with the updated values i.e. https://devices-api.com/name=test2&span=4
. This prevents my component which uses the data from the api response from loading. My render method is as such:
if (this.state.devices.length > 0) {
return (
<Bar
data={this.state.devices}
/>
);
} else {
return (
<div className="sweet-loading">
<HashLoader css={override} size={150} color={"#42a315"} />
</div>
);
}
}
I just see nonstop Hashloader and half rendered graph switching back and forth.
Upvotes: 0
Views: 145
Reputation: 49
After putting the api calls in the conditional in componentDidUpdate(prevProps)
. This issue was with the conditionals. I had to check the types for this.props.name
vs prevProps.name
. I used shallow-equal
to check as such:
componentDidUpdate(prevProps){
if (!shallowEqualObjects(prevProps.name, this.props.name)) {
// api call here
}
}
For reference: https://www.npmjs.com/package/shallow-equal
Upvotes: 0
Reputation: 3345
You should use componentDidUpdate instead For details check this link : https://reactjs.org/docs/react-component.html#componentdidupdate
Example:
componentDidUpdate(prevProps){
if(currentProps !== previProps){
<your api call goes here>
}
}
Upvotes: 2