I am developing an Order form in ReactJS for online shop. Now I get the message in browser console like 'this.state' is undefined inside a component function ... What is wrong? How can I avoid the problem? I did not find any clues in official documentation.
class Service extends React.Component {
constructor(props){
super(props);
this.state = {active: false,}
}
clickHandler(){
let active = !this.state.active;
this.setState({active: active});
this.props.addTotal((active == true ? this.props.price : -this.props.price));
}
render(){
return(
<p className={this.state.active ? 'active' : ''} onClick={() => this.clickHandler()}>
{this.props.name} <b>${this.props.price.toFixed(2)}</b>
</p>
);
}
};
class OrderForm extends React.Component {
constructor(){
super();
this.state = { total: 0,}
}
addTotal(price){
this.setState({total: this.state.total + price});
}
serviceList(){
var self = this;
//Iteration with map method
const serviceMapIterator = this.props.services.map(function(item, i, arr){
return (<Service key = {i.toString()}
name = {item.name}
price = {item.price}
active = {item.active}
addTotal= {self.addTotal} >
</Service>);
});
return serviceMapIterator;
}
render(){
let service = this.serviceList();
return(
<div>
{service}
<p id={'total'}>Total <b>${this.state.total.toFixed(2)}</b></p>
</div>
);
}
};
var services = [
{ name: 'Web Development', price: 300 },
{ name: 'Design', price: 400 }
];
How can I change it? What is the problem?
You call the addTotal() method defined in OrderForm (parent class) from Service (child class). You need addTotal have an access to "state" of the parent's class. So you are going to change your code either for constructor() by adding a row with .bind(this):
constructor(){
super();
this.state = { total: 0,};
this.addTotal = this.addTotal.bind(this);
}
or for serviceList() method by adding .bind(this) after the .map() of javascript method. Please, see below:
serviceList(){
var self = this;
//Iteration with map method
const serviceMapIterator = this.props.services.map(function(item, i, arr){
return (<Service key = {i.toString()}
name = {item.name}
price = {item.price}
active = {item.active}
addTotal= {self.addTotal} >
</Service>);
}.bind(this));
return serviceMapIterator;
}
When addTotal is called, this does not refer to the context of OrderForm Component. You should bind addTotal function like this in the constructor:
constructor() {
...
this.addTotal = this.addTotal.bind(this)
}
Your addTotal function looks like this:
addTotal(price){
this.setState({total: this.state.total + price});
}
As per DOCS
You should not write
this.setState({total: this.state.total + price});
You should use the second form of setState that accepts a callback function which receives previousState and previousProps as an argument.
addTotal(price) {
this.setState((prevState, previousProps) => ({
counter: prevState.total + price
}));
}
Similar change is required in clickHandler function.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.