简体   繁体   中英

React: 'this.state' of parent component is undefined inside a child component function

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM