Bomber
Bomber

Reputation: 10947

Cannot read property 'handleClick' of undefined when using map

I am trying to make a table row function like a Link with react-router.

I keep getting the error Cannot read property 'handleClick' of undefined

handleClick(user) {
   this.router.transitionTo('index', user);
}

render(){
   var userNodes = this.props.posts.map(function(user, i){
       return (
         <tr onClick={() => this.handleClick(user)}>
           <Td>{user.postId}</Td>
           <Td>{user.title}</Td>
           <Td>{user.body}</Td>   
         </tr>
       )
   });
...

Upvotes: 3

Views: 1911

Answers (3)

Mayank Shukla
Mayank Shukla

Reputation: 104369

Its a binding issue, you need to bind the context otherwise this will not point to the react component. Either use .bind(this) with function or use arrow function to avoid this kind of problem. Use this:

render(){
   var userNodes = this.props.posts.map(function(user, i){
       return (
         <tr onClick={() => this.handleClick(user)}>
           <Td>{user.postId}</Td>
           <Td>{user.title}</Td>
           <Td>{user.body}</Td>   
         </tr>
       )
   }.bind(this));

Or this:

render(){
   var userNodes = this.props.posts.map((user, i) => {
       return (
         <tr onClick={() => this.handleClick(user)}>
           <Td>{user.postId}</Td>
           <Td>{user.title}</Td>
           <Td>{user.body}</Td>   
         </tr>
       )
   });

Check the working example:

class App extends React.Component{

  handleClick(user){
    console.log(user);
  }

  render(){
   var data = [0,1,2,3,4].map((user, i) => {
       return (
         <tr onClick={() => this.handleClick(user)}>
           <td>{user}</td>
           <td>{user}</td>
           <td>{user}</td>   
         </tr>
       )
   });
   
   return(
      <table>
         <thead>
            <th>A</th>
            <th>B</th>
            <th>C</th>
         </thead>
         <tbody>
            {data}
         </tbody>
      </table>
   )
  }
}

ReactDOM.render(<App/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app'/>

Upvotes: 1

Bartek Fryzowicz
Bartek Fryzowicz

Reputation: 6674

Use arrow function as map callback to preserve component context (otherwise this inside the callback will not point to the component instance):

render(){
   var userNodes = this.props.posts.map((user, i) => {
       return (
         <tr onClick={() => this.handleClick(user)}>
           <Td>{user.postId}</Td>
           <Td>{user.title}</Td>
           <Td>{user.body}</Td>   
         </tr>
       )
   });

Upvotes: 4

Keyrr Perino
Keyrr Perino

Reputation: 81

You have to bind it.

var userNodes = this.props.posts.map(function(user, i){}.bind(this));

Upvotes: 0

Related Questions