React setState between components ES6

11,040

Solution 1

this is not auto-bound in ES6 style syntax.

Either:

  1. Bind in constructor like so: this.func = this.func.bind(this)
  2. Use arrow function syntax for the function in question like so: func = () => {};

More here: https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#autobinding

Solution 2

Use () => lambda to provide lexical scoping and bind correct value of this within the method handleStateClick():

handleStateClick = () => {
  this.setState({
    checkIn: newState
  });
}
Share:
11,040
Tom Pinchen
Author by

Tom Pinchen

Updated on June 04, 2022

Comments

  • Tom Pinchen
    Tom Pinchen almost 2 years

    I have a very simple application where I am trying to update the state of a parent component from a child component as follows:

    import React from '../../../../../../../dependencies/node_modules/react';
    import ReactDOM from '../../../../../../../dependencies/node_modules/react-dom';
    
    class CalendarMain extends React.Component {
        constructor() {
            super();
        }
    
        handleClick() {
            this.props.handleStateClick("State Changed");
        }
    
        render() {
            return ( 
                <div>
                    <div className="calendar">
                        {this.props.checkIn}
                        <button onClick={ this.handleClick.bind(this) }>Click Me</button>
                    </div>
                </div>
            )
        }
    }
    
    class CalendarApp extends React.Component {
    
        constructor() {
            super();
    
            this.state = { 
                checkIn: "Check-in",
                checkOut: "Check-out",
                dateSelected: false 
            };
        }
    
        handleStateClick( newState ) {
            this.setState({
                checkIn: newState
            });
        }
    
        render() {
    
            return (
                <div>
                    <CalendarMain 
                        checkIn = { this.state.checkIn }
                        handleStateClick = { this.handleStateClick.bind(this) }
                    />
                </div>
            );
        }
    }
    

    The error I am receiving is this.setState is not a function and I can't work out why. Any help would be much appreciated!

  • Sterling Archer
    Sterling Archer almost 8 years
    MDN documentation on arrow functions (lambdas) for more reference
  • Felix Kling
    Felix Kling almost 8 years
    You might want to explain that this feature is experimental and which Babel transforms to include to make this work.
  • Felix Kling
    Felix Kling almost 8 years
    The OP seem to bind it already: handleStateClick = { this.handleStateClick.bind(this) }.
  • Aditya Singh
    Aditya Singh almost 8 years
    Assuming that OP is already using ES6 classes and import, one would assume that they have all the prerequisite environment setup
  • Felix Kling
    Felix Kling almost 8 years
    Seems to be a bit of a stretch... are you aware that this is a proposal and not part of ES6?
  • Aditya Singh
    Aditya Singh almost 8 years
    I think it is part of ES6 as mentioned here: ecma-international.org/ecma-262/6.0/…. Maybe I am missing something and you can point me to some resource for what you are explaining. If you are referring to the use of transpilers, I think OP has set that up already
  • Felix Kling
    Felix Kling almost 8 years
    The syntax you are suggesting to use seems to be github.com/jeffmo/es-class-fields-and-static-properties . This is currently a stage 1 proposal, so the corresponding plugin or preset has to be added to enable this.