Reputation: 602
I am passing a self invoking function from App
Component into getBgColor
function of WeatherForecast
Component. This grabs a value from the child component WeatherForecast
and passes it into App
Component to update this.state.appColorClass
.
*getBgColor
function is inside componentDidUpdate()
which creates a loop and crashes the broweser. New to react and not sure how to solve this.
export default class App extends Component {
constructor(props) {
super(props);
this.state = { appColorClass: 'app-bg1' };
}
setAppColor(colorClass) {
alert("set className");
this.setState({ appColorClass: colorClass });
}
render() {
return (
<div className={"app-container " + this.state.appColorClass}>
<div className="main-wrapper">
<WeatherForecast getBgColor={color => this.setAppColor(color)} />
</div>
</div>
);
}
}
class WeatherForecast extends Component {
componentDidUpdate() {
console.log('Component DID UPDATE!')
//The function `setAppColor` from `App` component is passed into `getBgColor`
this.props.getBgColor(this.appColor(this.props.weather));
}
appColor(weatherData) {
console.log("app color working");
let temp = 0;
if ( typeof weatherData === 'undefined' || weatherData === null ) {
console.log(" initial Color went through");
return 'app-bg1';
}
temp = Math.round(weatherData.list[0].main.temp - 273.15);
if (temp <= -30) {
return "app-bg1";
}
if (temp >= -29 && temp <= -21) {
return "app-bg2";
}
if (temp >= -20 && temp <= -11) {
return "app-bg3";
}
if (temp >= -10 && temp <= 4) {
return "app-bg4";
}
if (temp >= 5 && temp <= 15) {
return "app-bg5";
}
if (temp >= 16 && temp <= 24) {
return "app-bg6";
}
if (temp >= 25 && temp <= 32) {
return "app-bg7";
}
if (temp >= 33 && temp <= 38) {
return "app-bg8";
}
if (temp >= 39) {
return "app-bg9";
}
}
render() {
return (
<div className="text-center col-xs-12">
<h1 id="temp">{this.displayTemp(this.props.weather)}<sup>°</sup></h1>
<h1>{this.displayCity(this.props.weather)}</h1>
</div>
);
}
}
Upvotes: 0
Views: 781
Reputation: 602
I ended up going with Johnny Klironomos's suggestion which returned true or false according to the Property value in shouldComponentUpdate
.
*this.props.weather
is undefined once the app loads because the user needs to pick a city to view its weather.
shouldComponentUpdate(nextProps) {
if(this.props.weather === 'undefined'){
return true
}
return this.props.weather !== nextProps.weather
}
Upvotes: 0
Reputation: 11093
The loop is recursive because after the WeatherForecast
component mounts (updating) it calls the getBgColor
prop, which sets parent state, which triggers a child update, which calls getBgColor
... and you get the picture.
Honestly, I would probably advise moving the logic around a little... since weather
is passed in as a prop and then the color is passed back up, it would seem more "React" like to handle that in the parent component. It's simpler to follow when data flows downstream. Assuming your requirements lead you to this position, adding a simple check in the setAppColor
would solve the issue.
setAppColor(colorClass) {
alert("set className");
// only set state if it's changing
if (colorClass != this.state.appColorClass) {
this.setState({ appColorClass: colorClass });
}
}
Upvotes: 1