Uncaught Typeerror: Cannot Read Property 'Author' of Undefined When Trying to Add Edit Functionality to a Comment Box

This is my React component. I've left some (unimportant) parts out. I am trying to add edit functionality to a comment, but I am running into an error (at the bottom).

export default class CommentBox extends React.Component {
  constructor() {
    super()

    this.state ={
      showComments: false,
      comments: [
        { id: uuid.v4(), author: 'Clu', body: 'Just say no to love!', avatarUrl: 'images/default-avatar.png' },
        { id: uuid.v4(), author: 'Anne Droid', body: 'I wanna know what love is...', avatarUrl: 'images/default-avatar.png' }
      ]
    }
  }

  render() {
    const comments = this._getComments() || [];

    let commentList;
    if (this.state.showComments) {
      commentList = <div className="comment-list">{comments}</div>
    }

    return(
      <div className="comment-box">
        <h3>COMMENTS</h3>
        {this._getPopularMessage(comments.length)}
        <h4 className="comment-count">{this._getCommentsTitle(comments.length)}</h4>
        <button className="comment-toggle" onClick={this._toggleShowComments.bind(this)}>{this._toggleCommentButton()}</button>
        <CommentForm addComment={this._addComment.bind(this)}/>
        {commentList}
      </div>
    );
  }

  _toggleShowComments(event) {
    event.preventDefault()
      this.setState({showComments: !this.state.showComments})
  }

  _addComment(author, body) {
    const comment = {
      id: uuid.v4(),
      author: author,
      body: body
    }

    this.setState({comments: this.state.comments.concat([comment])})
  }

  _getComments() {

    return this.state.comments.map((comment) => {
      return (<Comment
                 author={comment.author}
                 avatarUrl={comment.avatarUrl}
                 value ={comment.body}
                 editing={comment.editing}
                 onEditClick={this._activateEdit.bind(this, null, comment.id)}
                 key={comment.id}
                 onDelete = {this._deleteComment.bind(this, null, comment.id)}
                 onEdit={this._editComment.bind(this, null, comment.id)}/>)
    })
  }

  _activateEdit(event, key) {
    this.setState({comments: this.state.comments.map((comment) => {
      if (comment.id === key) {
        comment.editing = true
      }
      return comment
    })})
  }

This is where I think the error lies. If I leave out this section the code runs as expected. However, when I add this in I get an Uncaught TypeError: Cannot read property 'author' of undefined error. I'm not too sure why

  _editComment(event, key, value) {
    this.setState({comments: this.state.comments.map((comment) => {
      if (comment.id === key) {
        comment.editing = false
        comment.value = {value}
      console.log('edited!')
      }
    })})
  }
}

This is the Comment component for reference:

export default class Comment extends React.Component {
    constructor() {
      super();
      this.state = {
        isAbusive: false
      };
    }

    render() {
      let commentBody;
      if (!this.state.isAbusive) {
        commentBody = <div className='comment-body'>
                        <Editable
                        editing={this.props.editing}
                        value={this.props.value}
                        onEdit={this.props.onEdit}/>
                      </div>
      } else {
        commentBody = <em>Content marked as abusive</em>;
      }
      return(
        <div className="comment">
          <p className="comment-header">{this.props.author}</p>
            {commentBody}
          <div className="comment-actions">
            <VotingButtons />
            <a className='comment-actions-edit' href="#" onClick={this.props.onEditClick}>Edit comment</a>
            <a className='comment-actions-delete' href="#" onClick={this.props.onDelete}>Delete comment</a>
            <a className='comment-actions-abuse' href="#" onClick={this._toggleAbuse.bind(this)}>Report as abuse</a>
          </div>
        </div>
      );
    }

2 Answers

I highly recommend not mutating this.state.comments (as you're doing in the map), and instead return a new instance of it with the updated values.

_editComment(event, key, value) {
    this.setState({
        comments: this.state.comments.map((comment) => {
            if (comment.id === key) {
                return {
                    ...comment,
                    editing: false,
                    value: value
                }
            } 
            return comment;
        })
    })
}
2

comment.value = value instead of comment.value = {value}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Maya Lin-Takahashi

Maya Lin-Takahashi

Consumer Tech & Gadget Reviewer

Maya is a hardware enthusiast who tests and reviews smart home devices, smartphones, wearables, and audio gear. She focuses on practical consumer value and build quality.

Share this article
Twitter Facebook Pinterest