Reputation: 2290
I have a problem with infinite loop componentDidMount calling itself infinitely when I do something like this:
this.props.setRootState({industries: ['hello','world']});
Whole code looks like this:
import React from 'react';
import {Route, Link} from 'react-router-dom';
import FourthView from '../fourthview/fourthview.component';
import {Bootstrap, Grid, Row, Col, Button, Image, Modal, Popover} from 'react-bootstrap';
import Header from '../header/header.component';
import style from './information.style.scss';
import industryApi from '../industries/industry.api';
class InformationFilter extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
industryApi.getAll().then(response => {
if (response.data) {
this.props.setRootState({industries: response.data._embedded.industries});
} else {
console.log(response);
}
});
}
onIndustryChangeOption(event) {
this.props.setRootState({selectedIndustry: event.target.value});
}
onJobChangeOption(event) {
this.props.setRootState({selectedJob: event.target.value});
}
render() {
return (
<div className={"wrapperDiv"}>
<div className={"flexDivCol"}>
<div id="header">
<Header size="small"/>
</div>
<div id="industryFilter">
<h2 className={"center"} style={{marginBottom: '25px'}}>Tietoa Aloista</h2>
<p className={"primaryColor center"}>Valitse opintoala</p>
<div className={"industries dropdownListHolder center"}>
<select id={"dropdownList"} onChange={(e) => this.onIndustryChangeOption(e)}
value={this.props.rootState.selectedIndustry}>
{this.props.rootState.industries.map((industry, i) => <option key={i}
value={industry.id}>{industry.title}</option>)}
</select>
</div>
<p className={"primaryColor center"}>Valitse työtehtävä</p>
<div className={"jobs dropdownListHolder center"}>
<select id={"dropdownList"} onChange={(e) => this.onJobChangeOption(e)}
value={this.props.rootState.selectedJob}>
{this.props.rootState.industries.map((job, i) => <option key={i}
value={job.id}>{job.text}</option>)}
</select>
</div>
</div>
<div id="industryDescription">
<h4>Ravintola- ja cateringala</h4>
<p className={"secondaryColor"}>
Donec facilisis tortor ut augue lacinia, at viverra est semper.
Sed sapien metus, scelerisque nec pharetra id, tempor a tortor. Pellentesque non dignissim
neque. Ut porta viverra est, ut dignissim elit elementum ut. Nunc vel rhoncus nibh, ut
tincidunt turpis. Integer ac enim pellentesque, adipiscing metus id, pharetra odio.
</p>
<p className={"secondaryColor"}>
Donec facilisis tortor ut augue lacinia, at viverra est semper.
Sed sapien metus, scelerisque nec pharetra id, tempor a tortor. Pellentesque non dignissim
neque. Ut porta viverra est, ut dignissim elit elementum ut. Nunc vel rhoncus nibh, ut
tincidunt turpis. Integer ac enim pellentesque, adipiscing metus id, pharetra odio.
</p>
</div>
<div id={"btnFilter"}>
<Link to='/information-job'>
<div onClick={() => this.props.setRootState({globalVariable: 'bar'})}>
<Button className={"primaryBtn"}>Seuraava</Button>
</div>
</Link>
</div>
</div>
</div>
);
}
}
export default InformationFilter;
Routes.js
import React from "react";
import {HashRouter, Route, Switch, Redirect, Link} from 'react-router-dom';
import Main from './components/main/main.component';
import SecondView from './components/secondview/secondview.component';
import ThirdView from './components/thirdview/thirdview.component';
import Traineeship from './components/traineeship/traineeships.component';
import InformationFilter from "./components/information/information-filter.component";
import InformationJob from "./components/information/information-job.component";
class AppRoutes extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedIndustry: '',
selectedJob: '',
industries: [],
jobs: [],
}
}
render() {
const InformationFilterPage = () => <InformationFilter rootState={this.state}
setRootState={this.setState.bind(this)}/>;
const InformationJobPage = () => <InformationJob rootState={this.state}
setRootState={this.setState.bind(this)}/>;
const TraineeshipPage = () => <Traineeship rootState={this.state}
setRootState={this.setState.bind(this)}/>;
return (
<HashRouter>
<Switch>
<Route exact path='/' component={Main}/>
<Route path='/secondview' component={SecondView}/>
<Route path='/traineeships' component={TraineeshipPage}/>
<Route path='/information-filter' component={InformationFilterPage}/>
<Route path='/information-job' component={InformationJobPage}/>
<Redirect from='*' to='/'/>
</Switch>
</HashRouter>
);
}
}
export default AppRoutes;
Anyone knows what's happening here? I am keeping the state into this component due the cross passing values, you may say why dont you use redux but the thing is I dont want to use for this project as it is quite small project!
Upvotes: 0
Views: 2349
Reputation: 1636
When you call setState on the Parent component by setRootState it sets the state of the parent which intern causes a rerender of its children which causes the children to re-mount that calls componentDidMount which then again sets the state on the parent and the cycle continues.
To resolve this you chould call your your api and set the state in your parent component itself.
your Parent component should now have
componentDidMount() {
this.industryApiCall ()
}
industryApiCall = () => {
industryApi.getAll().then(response => {
if (response.data) {
this.props.setState({
industries: response.data._embedded.industries
})
} else {
console.log(response)
}
})
}
and you can pass this function to your children like
const InformationFilterPage = () => <InformationFilter rootState={this.state}
callApi={this.industryApiCall.bind(this)} />;
and use it inside your child comnponent by calling
this.props.callApi()
Upvotes: 4