Anto
Anto

Reputation: 4305

Uncaught TypeError in React component

I have created this small and simple script containing a React component:

var React = require('react');


var UsersList = React.createClass({

  handleRedirection: function(userName){
    window.location = '/user/'+userName;
  },
  render: function(){
return(
  <table>
    <tbody>
    <tr>
      <th>Name</th>
      <th>Surname</th>
      <th>Day of Birth</th>
      <th>Username</th>
      <th>Role</th>
      <th></th>
    </tr>
    {this.props.content.map(function(user, i) {
      return (
        <tr key={i}>
          <td>{user.name}</td>
          <td>{user.surname}</td>
          <td>{user.birthday}</td>
          <td>{user.userName}</td>
          <td>{user.userRole}</td>
          <td><button onClick={this.handleRedirection(user.userName)}>Open</button></td>
        </tr>
      );
    })}
    </tbody>
  </table>
 )
}
})


module.exports = UsersList;

When compiling, I do get in the browser the following error:

Uncaught TypeError: this.handleRedirection is not a function

I believe everything seems correct with the way the function is called, where the problem may be?

Upvotes: 0

Views: 89

Answers (3)

Piotr Berebecki
Piotr Berebecki

Reputation: 7468

I've prepared this demo for you: http://codepen.io/PiotrBerebecki/pen/ZpBwWz

You can use onClick={this.handleRedirection.bind(null, user.userName)} to create a new function without calling it on render. Also user.userName will be passed as the first argument.

var UsersList = React.createClass({

  handleRedirection: function(userName) {
    console.log(userName);
    window.location = '/user/' + userName;
  },
  render: function() {
    return (
      <table>
        <tbody>
        <tr>
          <th>Name</th>
          <th>Surname</th>
          <th></th>
        </tr>
        {this.props.content.map((user, i) => {
          return (
            <tr key={i}>
              <td>{user.name}</td>
              <td>{user.surname}</td>
              <td><button onClick={this.handleRedirection.bind(null, user.userName)}>Open</button></td>
            </tr>
          );
        })}
        </tbody>
      </table>
    )
  }
});

Upvotes: 1

Piotr Białek
Piotr Białek

Reputation: 2709

you need to bind this to function:

{this.props.content.map(function(user, i) {
  return (
    <tr key={i}>
      <td>{user.name}</td>
      <td>{user.surname}</td>
      <td>{user.birthday}</td>
      <td>{user.userName}</td>
      <td>{user.userRole}</td>
      <td><button onClick={this.handleRedirection.bind(null, user.userName)}>Open</button></td>
    </tr>
  );
}.bind(this))}

Upvotes: 3

TimoStaudinger
TimoStaudinger

Reputation: 42460

You are calling handleRedirection() directly and passing the return value as event handler instead of the function.

Instead, wrap the call into a function to call handleRedirection() only after the event was triggered:

<button onClick={function() {this.handleRedirection(user.userName)}.bind(this)}>

Upvotes: 1

Related Questions