Reputation: 317
I am new to react and its life-cycles, so currently following some tutorials and I am stuck with a problem that componentWillReceiveProps life-cycle method is not working the way I expect. The thing is that in App component I am passing prop isActive to Card component, and it is changing its value when input checkbox checked/unchecked, so I expect componentWillReceiveProps life-cycle method to be triggered. However, this is not working at all. Maybe anything you can advice me on that case? As well as I am open for the best practice advice. Thank you for your time in advance.
Components code:
//App.js
import React, {Component} from 'react';
import Ticker from "./Ticker/Ticker";
import currencies from './currencies';
import Card from "./Card/Card";
import uuid from "uuid";
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';
class App extends Component {
state = {
activePairs: []
};
handleCheckbox = (rateId, event) => {
const {checked} = event.target;
this.setState(({activePairs}) => {
let pairs = [...activePairs];
if (checked) {
if (!pairs.includes(rateId)) {
pairs.push(rateId);
}
} else {
let index = pairs.findIndex(rate => rate === rateId);
pairs.splice(index, 1);
}
return {
activePairs: pairs
};
});
};
render() {
return (
<div className="App">
<Ticker handleCheckbox={this.handleCheckbox.bind(this)}/>
<div className="container">
<div className="row">
{currencies.map(pair => <Card key={"card-" + uuid.v4()} currency={pair}
isActive={this.state.activePairs.includes(pair)}/>)}
</div>
</div>
</div>
);
}
}
export default App;
//Card.js
import React, {Component} from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import '../App.css';
class Card extends Component {
state = {
value: 0
};
componentWillReceiveProps(nextProp) {
console.log(nextProp);
if (!this.props.isActive && nextProp.isActive) {
this.updateExchangeRate();
this.interval = setInterval(this.updateExchangeRate, 3000);
} else if (this.props.isActive && !nextProp.isActive) {
clearInterval(this.interval);
this.setState({
value: 0
})
}
}
updateExchangeRate = () => {
return fetch(`https://www.cbr-xml-daily.ru/daily_json.js`).then(r => r.json()).then(res => {
let exRate = res["Valute"][this.props.currency.toUpperCase()]['Value'] + (Math.random() * (0.99 - 0.01 + 1) + 0.01);
let maximum = exRate + 5.00;
let minimum = exRate - 5.00;
this.setState({
value: (Math.floor(Math.random() * (maximum - minimum + 1)) + minimum).toFixed(2)
});
});
};
render() {
return (
<div className="col-md-3 col-sm-6 mb-3">
<div className="card text-center text-white bg-info">
<div className="card-header bg-info">{this.props.currency.toUpperCase() + " to RUB"}</div>
<div className="card-body">
<h5 className="card-title">Current exchange pair:</h5>
<p className="card-text">{this.state.value}</p>
</div>
</div>
</div>
);
}
}
export default Card;
//Ticker.js
import React, {Component} from 'react';
import currencies from "../currencies";
export default class Ticker extends Component {
state = {
currencies: currencies
};
render() {
return (
<div id="wrapper">
<div id="sidebar-wrapper">
<ul id="sidebar-ul" className="sidebar-nav">
{this.state.currencies.map(currency => {
return <li key={currency}>
<input id={currency + "-input"} type="checkbox" onChange=
{
this.props.handleCheckbox.bind(this, currency)
}/>
<label htmlFor={currency + "-input"} className="text-info"
role="button"> {currency.toUpperCase()} rate</label>
</li>
})}
</ul>
</div>
</div>
);
}
}
//currencies.js
export default ["aud", "azn", "gbp", "bgn", "usd", "eur"];
Upvotes: 1
Views: 657
Reputation: 317
Well, I finally found what was causing the problem here. In App component I was using uuid module as a key prop for every Card component, so because of it that was always rendering a new Card component each time isActive props were updating.
Solution: use a constant id instead as a key prop.
Upvotes: 1