Thinkster
React
CRUD Examples with React & Redux

Example 3: Displaying & Deleting Comments

Now that you can create a comment, let's implement the CommentList component:

Create src/components/Article/CommentList.js
import Comment from './Comment';
import React from 'react';

const CommentList = props => {
  return (
    <div>
      {
        props.comments.map(comment => {
          return (
            <Comment
              comment={comment}
              currentUser={props.currentUser}
              slug={props.slug}
              key={comment.id} />
          );
        })
      }
    </div>
  );
};

export default CommentList;

This component really just serves as a wrapper around the 'Comment' component, so let's implement that.

Create src/components/Article/Comment.js
import DeleteButton from './DeleteButton';
import { Link } from 'react-router';
import React from 'react';

const Comment = props => {
  const comment = props.comment;
  const show = props.currentUser &&
    props.currentUser.username === comment.author.username;
  return (
    <div className="card">
      <div className="card-block">
        <p className="card-text">{comment.body}</p>
      </div>
      <div className="card-footer">
        <Link
          to={`@${comment.author.username}`}
          className="comment-author">
          <img src={comment.author.image} className="comment-author-img" />
        </Link>
        &nbsp;
        <Link
          to={`@${comment.author.username}`}
          className="comment-author">
          {comment.author.username}
        </Link>
        <span className="date-posted">
          {new Date(comment.createdAt).toDateString()}
        </span>
        <DeleteButton show={show} slug={props.slug} commentId={comment.id} />
      </div>
    </div>
  );
};

export default Comment;

We're going to have links to the author and a delete button that shows up if you're the one who posted the comment. First let's add an HTTP call to delete a comment to agent.js:

Update src/agent.js
// ...
const Comments = {
  create: (slug, comment) =>
    requests.post(`/articles/${slug}/comments`, { comment }),
  delete: (slug, commentId) =>
    requests.del(`/articles/${slug}/comments/${commentId}`),
  forArticle: slug =>
    requests.get(`/articles/${slug}/comments`)
};
// ...

Next, let's add the 'DeleteButton' component and call this function in mapDispatchToProps():

Create src/components/Article/DeleteButton.js
import React from 'react';
import agent from '../../agent';
import { connect } from 'react-redux';

const mapDispatchToProps = dispatch => ({
  onClick: (payload, commentId) =>
    dispatch({ type: 'DELETE_COMMENT', payload, commentId })
});

const DeleteButton = props => {
  const del = () => {
    const payload = agent.Comments.delete(props.slug, props.commentId);
    props.onClick(payload, props.commentId);
  };

  if (props.show) {
    return (
      <span className="mod-options">
        <i className="ion-trash-a" onClick={del}></i>
      </span>
    );
  }
  return null;
};

export default connect(() => ({}), mapDispatchToProps)(DeleteButton);

Finally, we need to handle the 'DELETE_COMMENT' action in the article reducer:

Update src/reducers/article.js
export default (state = {}, action) => {
  switch (action.type) {
    // ...
    case 'DELETE_COMMENT':
      const commentId = action.commentId
      return {
        ...state,
        comments: state.comments.filter(comment => comment.id !== commentId)
      };
  }

  return state;
};

Now, when you navigate to an article page, you can write a comment, see it when the page reloads, and delete it.

Check your work

You can view the completed & working code from this tutorial here: