Noah R. Noah R. - 23 days ago 8
React JSX Question

React - Array Splice Trouble

Learning React. Attempting to make my own mini-app based very closely on what's done here: https://www.youtube.com/watch?v=-AbaV3nrw6E.

I'm having a problem with the deletion of comments in my app. I've looked in several other places for people having similar errors, but it seems the problem is within my own code (and yet I can find no errors). I've scoured the Babel file over and over, but to no avail.

Here are the specifics:
When you create a new comment, you have two options in the form of buttons: Save and Delete. After exactly one comment is written and you press "Save," the delete function works just fine. However, if there are three comments total (for example) and you click "delete" on the first one, the next comment (the second, in this case) is deleted.

Hopefully that makes some amount of sense.

Can you find my error? The math/logic behind the delete function is located on line 71 under the name "deleteComment."

Full Pen here.

var CommentSection = React.createClass({

getInitialState: function() {
return {editing: true}
},

edit: function() {
this.setState({editing: true});
},

save: function() {
this.props.updateCommentText(this.refs.newText.value, this.props.index);
this.setState({editing: false});
},

delete: function() {
this.props.deleteFromCard(this.props.index);
},

renderNormal: function() {
return (
<div className="comment-section">
<div className="comment-content">{this.props.children}</div>
<a className="-edit" onClick={this.edit}>Edit</a>
</div>
);
},

renderEdit: function() {
return (
<div className="comment-section">
<textarea ref="newText" defaultValue={this.props.children}></textarea>
<button className="-save" onClick={this.save}>Save</button>
<button className="-delete" onClick={this.delete}>Delete</button>
</div>
);
},

render: function() {
if(this.state.editing) {
return this.renderEdit();
} else {
return this.renderNormal();
}
}

});

var PhotoSection = React.createClass({

render: function() {
return <div className="photo-section"></div>;
}

});

var Desk = React.createClass({

getInitialState: function() {
return {
comments: []
}
},

addComment: function(text) {
var arr = this.state.comments;
arr.push(text);
this.setState({comments: arr})
},

deleteComment: function(i) {
console.log(i);
var arr = this.state.comments;
arr.splice(i, 1);
this.setState({comments: arr})
},

updateComment: function(newText, i) {
var arr = this.state.comments;
arr[i] = newText;
this.setState({comments: arr})
},

commentFormat: function(text, i) {
return (
<CommentSection key={i} index={i} updateCommentText={this.updateComment} deleteFromCard={this.deleteComment}>
{text}
</CommentSection>
);
},

render: function() {
return (
<div className="desk">
<div className="card">
<PhotoSection />
<div className="comment-section-backing">
<button className="-comment" onClick={this.addComment.bind(null, "")}>Leave a Comment</button>
{this.state.comments.map(this.commentFormat)}
</div>
</div>
</div>
);
}

});

ReactDOM.render(<Desk />, document.getElementById('app'));

Answer

There was an issue with using this.props.children when rendering the CommentSection component

Changing the code to use a prop:

    return (
      <div className="comment-section">
        <div className="comment-content">{this.props.commentText}</div>
        <a className="-edit" onClick={this.edit}>Edit</a>
        <button className="-delete" onClick={this.delete}>Delete</button>
      </div>
   );

and setting this in the commentFormat functiion in the container:

commentFormat: function(text, i) {
  return (
    <CommentSection 
      key={i} 
      index={i} 
      updateCommentText={this.updateComment}       
      deleteFromCard={this.deleteComment} 
      commentText={text}>
    </CommentSection>
        );
}

appears to work.

CodePen

Comments