1

My onchange function on my checkbox is always undefined. I made a sandbox to simplify my issue. I've tried changing it back and forth between an arrow and a regular function, and leaving the binding as its default state vs tying it to its binding in the constructor.

import "./styles.css";
import React, { Component } from "react";

class App extends Component {
  constructor(props) {
    super(props);

    this.renderCheckboxes = this.renderCheckboxes.bind(this);
    this.checkboxChange = this.checkboxChange.bind(this);
  }

  checkboxChange = (event) => {
    console.log("CHANGED");
  }

  renderCheckboxes(checkboxes) {
    return checkboxes.map(function (obj, idx) {
      return (
        <div>
          <label>{obj.name}</label>
          <input type="checkbox" onChange={this.checkboxChange} />
        </div>
      );
    });
  }

  render() {
    const cbList = [
      { name: "A", mood: "Happy" },
      { name: "B", mood: "Sad" },
      { name: "C", mood: "Mad" }
    ];

    return <>{this.renderCheckboxes(cbList)}</>;
  }
}

export default App;

My Sandbox

2 Answers 2

1

Your function is undefined because you are losing your context when your checkboxes.map happens.

  renderCheckboxes(checkboxes) {
    return checkboxes.map(function (obj, idx) { // here
      return (
        <div>
          <label>{obj.name}</label>
          <input type="checkbox" onChange={this.checkboxChange} />
        </div>
      );
    });
  }

You can change the function for an arrow function, so you won't lose context:

  renderCheckboxes(checkboxes) {
    return checkboxes.map((obj, idx) => { // here
      return (
        <div>
          <label>{obj.name}</label>
          <input type="checkbox" onChange={this.checkboxChange} />
        </div>
      );
    });
  }

It might not be the case, but if you need to send some parameter on your checkboxChange call, you could use it like this:

  checkboxChange = (value) => { // need to set the variable here
    console.log(value);
  }

  renderCheckboxes(checkboxes) {
    return checkboxes.map((obj, idx) => {
      return (
        <div>
          <label>{obj.name}</label>
          <input type="checkbox" onChange={() => this.checkboxChange('test')} />  <!-- so you can pass it from here -->
        </div>
      );
    });
  }
Sign up to request clarification or add additional context in comments.

Comments

1

Easy fix, it's because the binding doesn't work within the map function like you have now. To see this in action, try just rendering one checkbox, without map and you'll see your checkbox change method work.

Two changes I suggest:

  1. Change map method to an arrow function:
return checkboxes.map((obj, idx) => {
    ...
}
  1. Change onChange to an arrow function:
onChange={() => this.checkboxChange()}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.