Reputation: 9225
Layout.js
import React, {Component} from "react"
import Aircraft from "./Aircraft"
class Layout extends Component {
constructor(props) {
super(props)
this.state = {
test: true,
acn: ""
}
}
WhatIsAircraftName = (acn) => {
this.setState({
acn: acn
})
}
render() {
return (
<div>
<div className="mainD posRel hidO">
<div className="posRel hidO topD">
</div>
<div className="posRel hidO bottomD container">
<Aircraft clk={this.WhatIsAircraftName} />
</div>
</div>
</div>
)
}
}
export default Layout
Aircraft.js
import React, {Component} from "react"
import Loading from "./Loading"
class Aircraft extends Component {
constructor(props) {
super(props)
this.state = {
aircraft: [],
loading: false,
utilized: 0
}
}
componentDidMount() {
let mod_this = this
this.setState({
loading: true
})
fetch("https://some-endpoint")
.then(function(response) {
if (response.ok) {
return response.json()
}
})
.then(function(myJson) {
mod_this.setState({
aircraft: myJson,
loading: false
})
})
}
DisplayAircraft() {
let ac = this.state.aircraft
this.props.clk(ac.data[0].ident)
return (
<div className="acD posRel hidO selected">
{
<h2>{ac.data[0].ident}</h2>
}
</div>
)
}
render() {
const {aircraft} = this.state
return (
<div className="posRel hidO leftD">
<h1>Aircrafts</h1>
{
!aircraft || aircraft.length <= 0 || this.state.loading ?
<Loading /> :
this.DisplayAircraft()
}
</div>
)
}
}
export default Aircraft
When I run my app, I get setState loop error:
Unhandled Rejection (Invariant Violation): Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
The reason I am doing it like this is the Aircraft component will get the Aircraft ID which I want to send to another child component, hence I am sending it to the parent to use it as props for another component.
Section is:
Layout.WhatIsAircraftName [as clk]
Upvotes: 1
Views: 75
Reputation: 111
Try something like this, I've moved the logic around that you are no longer updating the state from the render function.
import React, {Component} from "react"
import Loading from "./Loading"
class Aircraft extends Component {
constructor(props) {
super(props)
this.state = {
aircraft: [],
loading: false,
utilized: 0
}
}
componentDidMount() {
let mod_this = this
this.setState({
loading: true
})
fetch("https://some-endpoint")
.then(function(response) {
if (response.ok) {
return response.json()
}
})
.then(function(myJson) {
this.props.clk(myJson.data[0].ident)
mod_this.setState({
aircraft: myJson,
loading: false
})
})
}
render() {
const {aircraft} = this.state
return (
<div className="posRel hidO leftD">
<h1>Aircrafts</h1>
{
!aircraft || aircraft.length <= 0 || this.state.loading ?
<Loading /> :
(<div className="acD posRel hidO selected">
<h2>{aircraft.data[0].ident}</h2>
</div>)
}
</div>
)
}
}
export default Aircraft
This should at least get it working for you but based on what I can see in your code I do have another suggestion. It would be much simpler to do the API call from the Layout component and then pass the aircraft information down to the Aircraft component via Props. In your current code you are having to pass the data back up via a function you passed via a prop which makes it all a little more complicated. React tends to be much easier to work with when you are passing data down the chain.
Hope that helps!
Upvotes: 1
Reputation: 5650
The problem is that your render
method is not pure and is updating state.
The render() function should be pure, meaning that it does not modify component state, it returns the same result each time it’s invoked, and it does not directly interact with the browser. - React Docs
In your parent component, you have WhatIsAircraftName
which is calling setState
. Whenever this method is invoked, it will trigger a state update which will trigger a render. In the parent's render
you are passing the Aircraft
component the prop clk
which is assigned to WhatIsAircraftName
. Then, in Aircraft
's render
, it's calling DisplayAircraft
, which is invoking the prop clk
which starts us back at the top.
Layout#render
-> Aircraft#render
-> DisplayAircraft
-> this.props.clk
-> WhatIsAircraftName
-> this.setState
-> Layout#render
-> etc. (infinite loop).
This loop needs to be broken, setState
should never be invoked within render
.
Upvotes: 3