user47143
user47143

Reputation: 75

React JS - event handling for mapped objects

I'm trying to figure out a way to pass a (event.target) from a child component that has been mapped to a parent component. The problem is, when I map it, any property I try to set with "this" becomes undefined.

example:

var OptionChoices = [
  {value: 'bad', label: "Select a field"},
  {value: 'blue', label: "Blue"},
  {value: 'red', label: "Red"},
  {value: 'green', label: "Green"},
  {value: 'pink', label: "Pink"}
  ];

var CategoryRow = React.createClass({
  getInitialState: function () {
    return{array : [{order: "1"}]};
    },
  onChange: function(event){
    console.log("YAY");
    },
  render: function() {
    return (
      <div className={this.props.categoryClass}>
        <h3>{this.props.text}</h3>
        {this.state.array.map(function(option){
          return (
            <Dropdown onChange={this.onChange} options={OptionChoices} key={option.order} />
            );
        })}
    </div>
    );
  }
});

var Dropdown = React.createClass({
  getInitialState: function () {
    return{firstTime: true};
  },
  onChange: function(event){
    var x = event.target;
    if (this.state.firstTime===true) {
      if (typeof this.props.onChange === 'function') {
        this.props.onChange(event.target);
    }
  }
    this.setState({firstTime: false});
  },
  render: function() {
    return (
      <select onChange={this.onChange} className={this.props.dropdownClass}>
        {this.props.options.map(function(option){
          return (
              <Option value={option.value} key={option.value}>{option.label}</Option>
            );
        })}
    </select>
    );
  }
});

Right now I get an error "Cannot read property 'onChange' of undefined"

Any/all ideas appreciated. Thanks!

Upvotes: 0

Views: 1150

Answers (1)

Abhishek Jain
Abhishek Jain

Reputation: 2977

This is because within the map function, this doesn't refer to the outer context (your component).

To fix this, you need to tell the map function what context to use.. You can do this as follows (notice the this at the end):-

this.state.array.map(function(option){
      return (
        <Dropdown onChange={this.onChange} options={OptionChoices} key={option.order} />
        );
    }, this)

Or, alternatively if you are using ES6, you can use arrow functions (which capture the 'this' value of the enclosing context). So your map will convert into something like:-

this.state.array.map(option => {
      return (
        <Dropdown onChange={this.onChange} options={OptionChoices} key={option.order} />
        );
    })

Upvotes: 3

Related Questions