JS/React - cannot read property "X" of undefined, unable to access method

1.9k views Asked by At

bit of a React noob here and I've searched a fair bit for solutions to this issue, however I'm still confused. In short, I have a dropdown menu with a list of numbers, rendered from an array via map. The intent is to be able to change the value of "coloursValue" via setState by clicking on one of the buttons from the dropdown menu. Everything renders correctly, however when I attempt to click one of the buttons I am met w/ the error message "TypeError: Cannot read property 'changeValue' of undefined". I understand this is likely an issue relating to scope and "this" not being properly defined, yet changeValue is bound in the constructor. What am I doing wrong, and how can I rectify this?

Thank you very much in advance.

let colours = [1, 2, 3, 4, 5];

let coloursMapped = mapItems(colours, "coloursValue");


function mapItems(input, context) {
  let listItems = input.map(item =>
  <DropdownItem key={item}>
    <button onClick={() => this.changeValue.bind(this)}>
      {item}
    </button>
  </DropdownItem>
  );
  return <DropdownMenu right>
    {listItems}
  </DropdownMenu>
}

class App extends Component {

constructor(props) {
  super(props);

  this.changeValue = this.changeValue.bind(this);
  this.toggle = this.toggle.bind(this);
  this.state = {
    coloursValue: "# of Colours",
    dropdownOpen: [false, false, false]
  };
}

changeValue(value, context) {
  // modify "coloursValue" via setState according to the number 
  // selected via the "onClick" handler in "mapItems"
}

toggle(index) {
  let dropdownState = this.state.dropdownOpen.slice();
  dropdownState[index] = !this.state.dropdownOpen[index];
  this.setState({
    dropdownOpen: dropdownState
  });
}
1

There are 1 answers

3
Chase DeAnda On BEST ANSWER

It's because mapItems exists outside of the class, so it doesn't have access to the class scope to bind changeValue. Move mapItems into the App component and it should work. You should also move colours and coloursMapped into the App component as state.