1

I keep getting the following error:

TypeError: this.props.onDelete is not a function

I have .bind(this) on the functions in render(), but this error seems to keep occurring and I don't know why. Here is the relevant code:

App.js

import React, {Component} from 'react';
import Todos from './Components/Todos';

class App extends Component {

  deleteTodo(id) {
    let todos = this.state.todos;

    for (let i = 0; i < todos.length; i++) {
      if (todos[i].id === id) {
        todos.splice(i, 1);
        break;
      }
    }

    this.state.todos = todos;
  }

  render() {


    return (<div className="App">
      <h1>React Todo App</h1>

      <AddTodo/>
      <Todos todos={this.state.todos} onDelete={this.deleteTodo.bind(this)}/>
    </div>);
  }
}

export default App;

Todos.js

import React, {Component} from 'react';
import Todo from './Todo';

class Todos extends Component {

  delete(id) {
    this.props.onDelete(id);
  }

  render() {

    let todoItems = '';

    if (this.props.todos) {

      todoItems = this.props.todos.map(todo => {
        return (<Todo id={todo.id} name={todo.name})></Todo>)
      });
    }

    return (<ul class="todos" onDelete={this.props.onDelete.bind(this)}>{todoItems}</ul>);
  }
}

export default Todos;

Todo.js

import React, {Component} from 'react';

class Todo extends Component {

  delete(id) {
    this.props.onDelete(id);
  }

  render() {
    return (<li class="todo" id={this.props.id}>{this.props.name}
      <a onClick={this.delete.bind(this, this.props.id)} class='remove-button' href='#'>X</a>
    </li>)
  }

}

export default Todo;

The error seems to be occurring at Todo.js in the following code snippet:

delete(id) {
    this.props.onDelete(id)    // Error
}

Edit: Added more code for context

  • I'm afraid you haven't shown enough of the code. My guess is that your `li` creation is in a `map` callback or similar and losing `this` that way, but... Please update your question with a [mcve] demonstrating the problem, ideally a **runnable** one using Stack Snippets (the `[<>]` toolbar button). Stack Snippets support React, including JSX; [here's how to do one](http://meta.stackoverflow.com/questions/338537/). – T.J. Crowder Jul 09 '18 at 14:00
  • Can you check this above url since you will get an idea https://stackoverflow.com/a/31141861/8574868 – Sathish Ravichandran Jul 09 '18 at 14:02
  • Tholle's answer below is correct (if it's not *the* problem, it's certainly *a* problem, and it probably is *the* problem), but with more context we could probably suggest better ways of doing it. – T.J. Crowder Jul 09 '18 at 14:04
  • @T.J.Crowder Your right, I was passing onDelete through
      instead of . I didn't include the map() in my original post. I have edited the post so you can observe my mistake.
      – Curious Spider Jul 09 '18 at 20:47
    • Please do read through the two things I liked above, [mcve] and [how to do a React Stack Snippet](http://meta.stackoverflow.com/questions/338537/). Your "snippets" above aren't runnable, they should just be code blocks. But providing a runnable snippet [following those instructions](http://meta.stackoverflow.com/questions/338537/) would help tremendously. – T.J. Crowder Jul 10 '18 at 07:09

    1 Answers1

    2

    By writing this.delete(this.props.id).bind(this) you are calling your this.delete function instead of giving onClick a function reference.

    You could write it like this:

    onClick={this.delete.bind(this, this.props.id)}
    

    Or use an arrow function:

    onClick={() => this.delete(this.props.id)}
    
    Tholle
    • 108,070
    • 19
    • 198
    • 189
    • Sorry for not adding more context in the original post, I've edited the post to add more code for context. I believe my problem was that in Todos.js, I wasn't passing onDelete through the element, instead, I was passing it through the
        element.
        – Curious Spider Jul 09 '18 at 20:44