简体   繁体   中英

TypeError: undefined is not an object (evaluating 'this.props') when trying to use callback between child and parent in React.js

I'm currently having a problem when trying to send an action from a child element to its parent element. I want to change the state of the MessagingContainer when a thread is clicked to mark that thread as the active thread. So when the thread ( ThreadElement ) is clicked, it needs to send to its parent ( ThreadList ), which then sends to its parent ( MessagingContainer ) in order for the Messaging Container to update the state.

Firstly, is this the right approach, RE: state and modifying state?

Secondly, I can't seem to get this working. I'm getting a persistent error of TypeError: undefined is not an object (evaluating 'this.props') .

I've omitted the messages part of the code below so only the threads is visible.

var ThreadElement = React.createClass({
  render: function() {
    console.log('ThreadElement');
    console.log(this.props);
    var threadParticipantsNames = this.props.thread.participants.map(function(participant) {
      var participantName;
      if (participant.user) {
        participantName = participant.user.metadata.first_name;
      } else {
        participantName = 'Anonymous';
      }

      return (
        <span key={participant.id}>
          {participantName}
        </span>
      );
    });
    return (
      <div key={this.props.thread.id} onClick={this.props.handleActiveThreadChange}>
        {threadParticipantsNames}
      </div>
    );
  }
});


var ThreadList = React.createClass({
  render: function() {
    console.log('ThreadList');
    console.log(this.props);
    var threadNodes = this.props.threads.map(function(thread) {
      return (
        <ThreadElement thread={thread} key={thread.id} handleActiveThreadChange={this.props.handleActiveThreadChange} />
      );
    });
    return (
      <div className="threadList">
        {threadNodes}
      </div>
    );
  }
});


var MessagingContainer = React.createClass({
  handleActiveThreadChange: function() {
    console.log('MessagingContainer handleActiveThreadChange called.');
  },
  getInitialState: function() {
    return {
      activeThread: 0,
      data: threadsJSON
    };
  },
  render: function() {
    console.log('MessagingContainer');
    console.log(this.props);
    return (
      <div>
        <ThreadList threads={this.state.data.threads} handleActiveThreadChange={this.handleActiveThreadChange} />
        <MessageList thread={this.state.data.threads[this.state.activeThread]} />
      </div>
    );
  }
});

The console gives the below output, if that helps. The MessagingContainer and ThreadList console.log()s seem to work, so does this suggest the issue is in the ThreadElement class?

[Log]   MessagingContainer
[Log]   {}
[Log]   ThreadList
[Log]   {threads: Array, handleActiveThreadChange: function}
[Error] TypeError: undefined is not an object (evaluating 'this.props')

Thanks!

From what I can see, I think the problem is your .map function in the ThreadList component. Your context has changed for this since you're inside the map function. You should use .bind or a local that = this variable to save the right context:

var threadNodes = this.props.threads.map(function(thread) {
  return (
    <ThreadElement thread={thread} key={thread.id} handleActiveThreadChange={this.props.handleActiveThreadChange} />
  );
}).bind(this);

or

var that = this;
var threadNodes = this.props.threads.map(function(thread) {
  return (
    <ThreadElement thread={thread} key={thread.id} handleActiveThreadChange={that.props.handleActiveThreadChange} />
  );
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM