Skip to content

TypeError: Cannot read property ‘handleChange’ of undefined

I am trying to build a todo list app with React. Getting the error “Cannot read property of handleChange undefined”. Below is the code i am working on. Moreover, todosData is an array of objects having id, text and completed(boolean – true/false) as properties.

    import React from "react";
    import './App.css';
    import List from './Components/Todo-Startup/content';
    import todosData from './Components/Todo-Startup/todosData';
    class App extends React.Component {
         constructor(){
            super()
              this.state = {
              todos: todosData
          }
          this.handleChange = this.handleChange.bind(this)
  }
    handleChange(id){
         console.log("Changed", id)
  }
    render() {
         const todoComponents = this.state.todos.map(function(task){
             return (
               <List key={task.id}
                  task={task}
                  handleChange={this.handleChange} />
      )
    })
  return (
    <div className = "App">
      {todoComponents}
    </div>
  )
 }
 }
   export default App;

The content.js is as follows,

import React from 'react';
const List = function (props){
    return (
        <div className="todo-list">
            <input
                onChange={function(){props.handleChange(props.task.id)
            }}
                type="checkbox"
                checked={props.task.completed}/>
                <p>{props.task.text}</p>
        </div>
    );
}
export default List;

And finally the array todosData,

    const todosData = [
    {
        id: 1,
        text: "Take out the trash",
        completed: true
    },
    {
        id: 2,
        text: "Grocery Shopping",
        completed: false
    },
    {
        id: 3,
        text: "Get a hair cut",
        completed: true
    },
    {
        id: 4,
        text: "Study & Practice JavaScript",
        completed: true
    }
]
export default todosData;

Answer

Because this is function-scoped, except for arrow-functions.

const todoComponents = this.state.todos.map(task => (
    <List key={task.id}
          task={task}
          handleChange={this.handleChange} />
))

Alternative, if you have to use function.

const that = this;
const todoComponents = this.state.todos.map(function (task) (
    <List key={task.id}
          task={task}
          handleChange={that.handleChange} />
));

See also How to access the correct `this` inside a callback?