0

I'm sorry if this sounds like a newbish question. Haven't managed to find an answer yet.

I am basically trying to use use a class's method as a callback to the onClick in my JSX.

Here is the code of my App component:

import React from 'react';
import PropTypes from 'prop-types';

class App extends React.Component {
  constructor(props) {
      super(props);
      this.deletePost = this.deletePost.bind(this);
  }

  deletePost() {
    //   this.props.posts = this.props.posts.splice(i,1)
    console.log("Deleted the post");
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <h1 className="App-title">Welcome to learn React</h1>
        </header>

        <div>
            <input type="text"/>
            <button>Post</button>
        </div>

        <br/>

        <div className="post-list">
            <hr/>
            {this.props.posts.map(function(post, i){
               return <div>
                    {post} - {i}
                    <button onClick={this.deletePost}>Del</button>
                    <hr/>
                </div>;
            })}
        </div>

      </div>
    );
  }
}

App.propTypes = {
  posts: PropTypes.array
};

export default App;

The error I get is as follows:

TypeError: Cannot read property 'deletePost' of undefined
(anonymous function)
src/components/App.js:34
  31 | {this.props.posts.map(function(post, i){
  32 |    return <div>
  33 |         {post} - {i}
> 34 |         <button onClick={this.deletePost}>Del</button>
  35 |         <hr/>
  36 |     </div>;
  37 | })}

So my question is how do I get pass in the deletePost function to the onClick?

0

4 Answers 4

1

the problem is that this is undefined inside you map function callback. Can you use arrow functions? Do you have necessary transpilation? If yes, using an arrow function will solve that:

{this.props.posts.map((post, i) => { // <-- arrow function
    return <div>
        {post} - {i}
        <button onClick={this.deletePost}>Del</button>
        <hr/>
    </div>;
})}

If you can't or don't want to use arrow function in there, you can do something like that:

render() {
const deletePost = this.deletePost; // Save variable while we have access to this
return (
  <div className="App">
    <header className="App-header">
      <h1 className="App-title">Welcome to learn React</h1>
    </header>

    <div>
        <input type="text"/>
        <button>Post</button>
    </div>

    <br/>

    <div className="post-list">
        <hr/>
        {this.props.posts.map(function(post, i){
           return <div>
                {post} - {i}
                <button onClick={deletePost}>Del</button>
                <hr/>
            </div>;
        })}
    </div>

  </div>
);

}

Sign up to request clarification or add additional context in comments.

2 Comments

Or one may use .bind(this) on the anonymous function passed to map: this.props.posts.map(function (...) {...}.bind(this)).
Both the answer and this comment above helped. Thanks a bunch @Gleb Kost and ArneHugo
1

TypeError: Cannot read property 'deletePost' of undefined?

Its issue with this binding.Use arrow function to come over the issue.

 {this.props.posts.map((post, i)=>{
                   return <div>
                        {post} - {i}
                        <button onClick={this.deletePost}>Del</button>
                        <hr/>
                    </div>;
                })}

Comments

0

For intended value of this, use ES6 arrow function:

{this.props.posts.map((post, i) => {
  return (
    <div>
      {post} - {i}
      <button onClick={this.deletePost}>Del</button>
      <hr/>
    </div>
   );
 }}

Comments

0

Try Arrow functions (Es6 feature):

     constructor(props) {
         super(props);
      }

      deletePost = () => {
           console.log("Deleted the post");
       }

 inside map function also use arrow

   {this.props.posts.map((post, i) => {
           return <div>
                {post} - {i}
                <button onClick={this.deletePost}>Del</button>
                <hr/>
            </div>;
        })}

Must be change : babel presets es2015 --> es2016 and also to add stage-2

ex:
   Webpack.js

 module: {
   loaders: [
      {
         test: /\.jsx?$/,
         exclude: /node_modules/,
         loader: 'babel-loader',
         query: {
            presets: ['es2016', 'react', 'stage-2'] //Add ES6 features 
         }
      }
   ]
}

3 Comments

this will still throw the same error
check webpack configuration
ok, with the last edit to the map callback, it will work

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.