React: TypeError: Cannot read property 'state' of undefined with create-react-class

Created on 25 Jan 2018  路  10Comments  路  Source: facebook/react

I am currently attempting to create a button which is red with the text "Yes" that when you click on it the button changes to a green color with the text "Confirm?" before the final stage in which an action takes place. Where I am currently at is defining buttonColor as a state which changes on the click of the button; the initial color should be #FD8F83 and the final color after the click should be #A4D87C. However, I am currently getting the error "TypeError: Cannot read property 'state' of undefined" pointing to the style={{backgroundColor: this.state.buttonColor}} line whenever the code is compiled on the webpage.

Defining initial state and behavior on click:

getInitialState: function() {
        return {
            buttonColor: "#FD8F83"
        };
},
handleClick(color) {
        this.setState({
        buttonColor: color
    }); 
}

Code inside table in render():

<td>
    <button 
        className="removeButton" 
        style={{backgroundColor: this.state.buttonColor}} 
        onClick={function(){this.handleClick("#A4D87C")}}>
        Yes
    </button>
</td>

Does anyone have any ideas why this is? I am brand new to React so I apologize if it's obvious. I also learned React using createClass so I've been trying to piece together how to make this work with the new create-react-class package. Any advice is greatly appreciated!

React: ^16.2.0
Chrome: Version 63.0.3239.132 (Official Build) (64-bit)

Question

Most helpful comment

@dallashuggins replace

this.props.customers.map(function(customer, index) {

with

this.props.customers.map((customer, index) => {

and that should fix it. The function keyword switches the context of this to be whatever object the function is bound to, in this case it's undefined. Arrow functions were added to JavaScript because of this behavior since they do not change the context of this.

Also for future reference this is an issue thats better for some place like Stack Overflow, these threads are for tracking bugs.

All 10 comments

Please provide the full code. (Otherwise it's hard to tell)

Hi @gaearon - here it is:

import React from 'react'; 
import {
    Table
} from 'react-bootstrap';
var createReactClass = require('create-react-class');

var Customers = createReactClass({
    getInitialState: function() {
        return {
            buttonColor: "#FD8F83"
        };
    },
    handleClick(color) {
        console.log("Button Color (state):", this.state.buttonColor);
        this.setState({buttonColor: color}); 
    },
    render() {
        return (
        <Table striped bordered condensed hover>
            <thead>
                <tr>
                    <th>#</th>
                    <th>Customer Name</th>
                    <th>Username</th>
                    <th>Addl Username</th>
                    <th>Remove?</th>
                </tr>
            </thead>
            <tbody>
                {this.props.customers.map(function(customer, index) {
                    return (
                       <tr>
                            <td>{index + 1}</td>
                            <td>{customer.name}</td> 
                            <td>{customer.fb_un}</td> 
                            <td>{customer.em_un}</td>
                            <td>
                                <button 
                                    className="removeButton" 
                                    style={{backgroundColor: this.state.buttonColor}} 
                                    onClick={function(){this.handleClick("#A4D87C")}}>
                                    Yes
                                </button>
                            </td>
                       </tr>
                    );
                })}
            </tbody>
        </Table>
        ); 
    }
});

export default Customers; 

@dallashuggins replace

this.props.customers.map(function(customer, index) {

with

this.props.customers.map((customer, index) => {

and that should fix it. The function keyword switches the context of this to be whatever object the function is bound to, in this case it's undefined. Arrow functions were added to JavaScript because of this behavior since they do not change the context of this.

Also for future reference this is an issue thats better for some place like Stack Overflow, these threads are for tracking bugs.

The problem is:

onClick={function(){this.handleClick("#A4D87C")}}

In JS this does not get preserved this way.

If you want to keep this value from the render method you can use an arrow function:

onClick={() => {this.handleClick("#A4D87C")}}

Hope this helps!

Oh, and the above answer is also right (I missed that). Use arrows in both cases.

That worked! Thank you both so much!

not update state value,Please help

this.setState({ entityArray: resultEntities }, () => {
console.log(this.state.entityArray, 'entityArray');
});

you are not binding tour function , try to bind in constructor like :

 constructor(props) {
   super();

  // binsings
  this.myFunction = this.myFunction.bind(this)
}

binding in render will create a function in each render , and that will cause a small performance issue, so its best practice to bind in class constructor instead

gh

Hi @gaearon - here it is not working i tried

import React from 'react'; 
import {
    Table
} from 'react-bootstrap';
var createReactClass = require('create-react-class');

var Customers = createReactClass({
    getInitialState: function() {
      return {
          buttonColor: "#FD8F83"
      };
    },
    handleClick(color) {
      console.log("Button Color (state):", this.state.buttonColor);
      this.setState({buttonColor: color}); 
    },
    render() {
        return (
      <Table striped bordered condensed hover>
          <thead>
              <tr>
                  <th>#</th>
                  <th>Customer Name</th>
                  <th>Username</th>
                  <th>Addl Username</th>
                  <th>Remove?</th>
              </tr>
          </thead>
          <tbody>
              {this.props.customers.map(function(customer, index) {
                  return (
                     <tr>
                          <td>{index + 1}</td>
                          <td>{customer.name}</td> 
                          <td>{customer.fb_un}</td> 
                          <td>{customer.em_un}</td>
                          <td>
                              <button 
                                  className="removeButton" 
                                  style={{backgroundColor: this.state.buttonColor}} 
                                  onClick={function(){this.handleClick("#A4D87C")}}>
                                  Yes
                              </button>
                          </td>
                     </tr>
                  );
              })}
          </tbody>
      </Table>
      ); 
  }
});

export default Customers; 

const suppliers = this.state.bgpValidationData.map(function (data, idx) {
const details = '';
{ console.log(JSON.stringify(this)) }
return
{console.log(JSON.stringify(data))}
expandIcon={}>

      <Container className="noP col-sm-6" maxWidth="false"><a target="_blank" href={data.REQUEST.validationURL + '?url=specials:${' + data.REQUEST.CID + '}'} >{data.REQUEST.CID} </a></Container>
      <Container className="noP col-sm-2" maxWidth="xs"> <FormLabel >{data.REQUEST.EVENT}</FormLabel></Container>
      <Container className="noP col-sm-2" maxWidth="xs">  <FormLabel > {data.REQUEST.CKT_TYPE} </FormLabel></Container>
      <Container className="noP col-sm-2" maxWidth="xs">  <FormLabel > {data.REQUEST.CKT_LAYER}</FormLabel></Container>
    </ExpansionPanelSummary>
    <ExpansionPanelDetails>
      <Typography>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex,
        sit amet blandit leo lobortis eget.
              </Typography>
    </ExpansionPanelDetails>
  </ExpansionPanel>

})
return (
  <div>{suppliers}</div>
);
Was this page helpful?
0 / 5 - 0 ratings