Skip to content

Commit

Permalink
implement useReducer for comment state management #9365 (#9801)
Browse files Browse the repository at this point in the history
  • Loading branch information
noi5e authored Jun 15, 2021
1 parent 00fbfce commit 596ff0c
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 26 deletions.
52 changes: 26 additions & 26 deletions app/javascript/components/CommentsContainer.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { useState } from "react";
import React, { useReducer, useState } from "react";
import PropTypes from "prop-types";

import { UserContext } from "./user-context";
import { makeDeepCopy } from "./helpers";
import { reducer } from "./reducers";

import CommentForm from "./CommentForm";
import CommentsHeader from "./CommentsHeader";
Expand All @@ -14,8 +14,13 @@ const CommentsContainer = ({
initialTextAreaValues,
nodeId
}) => {
// React Hook: Comments State
const [comments, setComments] = useState(initialComments);
const initialState = {
comments: initialComments,
commentFormsVisibility: initialCommentFormToggleState,
textAreaValues: initialTextAreaValues
}

const [state, dispatch] = useReducer(reducer, initialState);

// React Hook: Visibility for Reply and Edit Comment Forms
const [commentFormsVisibility, setCommentFormsVisibility] = useState(initialCommentFormToggleState);
Expand Down Expand Up @@ -66,8 +71,11 @@ const CommentsContainer = ({
if (!data.comment[0].replyTo) {
setCommentFormsVisibility(oldState => ({ ...oldState, ["reply-" + newCommentId]: false }));
}
// push the comment into state
setComments(oldComments => ([...oldComments, data.comment[0]]));
// call useReducer's dispatch function to push the comment into state
dispatch({
type: "CREATE COMMENT",
newComment: data.comment[0]
})
// close the comment form
if (formType !== "main") {
setCommentFormsVisibility(oldState => (Object.assign({}, oldState, { [formId]: false })));
Expand All @@ -87,18 +95,11 @@ const CommentsContainer = ({
body: commentBody
},
function(data) {
// the freshly updated comment is NOT a reply
for (let i = 0; i < comments.length; i++) {
// find the comment in state
if (comments[i].commentId === data.comment[0].commentId) {
let newComment = makeDeepCopy(comments[i]);
newComment.htmlCommentText = data.comment[0].htmlCommentText; // update comment text
newComment.rawCommentText = data.comment[0].rawCommentText;
// keep most of oldComments, but replace the comment at index i with newComment.
setComments(oldComments => (Object.assign([], oldComments, { [i]: newComment })));
break;
}
}
// call useReducer's dispatch function to update the comment in state
dispatch({
type: "UPDATE COMMENT",
newComment: data.comment[0]
})
// close the edit comment form
setCommentFormsVisibility(oldState => (Object.assign({}, oldState, { [formId]: false })));
notyNotification('mint', 3000, 'success', 'topRight', 'Comment Updated!');
Expand All @@ -114,12 +115,11 @@ const CommentsContainer = ({
},
function(data) {
if (data.success) {
for (let i = 0; i < comments.length; i++) {
if (comments[i].commentId === commentId) {
setComments(oldState => (oldState.filter(comment => comment.commentId !== commentId)));
notyNotification('sunset', 3000, 'error', 'topRight', 'Comment deleted');
}
}
dispatch({
type: "DELETE COMMENT",
commentId
})
notyNotification('sunset', 3000, 'error', 'topRight', 'Comment deleted');
}
}
)
Expand All @@ -130,10 +130,10 @@ const CommentsContainer = ({
{currentUser => (
<div id="legacy-editor-container" className="row">
<div id="comments" className="col-lg-10 comments">
<CommentsHeader comments={comments} />
<CommentsHeader comments={state.comments} />
<CommentsList
commentFormsVisibility={commentFormsVisibility}
comments={comments}
comments={state.comments}
currentUser={currentUser}
handleCreateComment={handleCreateComment}
handleDeleteComment={handleDeleteComment}
Expand Down
50 changes: 50 additions & 0 deletions app/javascript/components/reducers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* eslint-disable complexity */
import { makeDeepCopy } from "./helpers";

const reducer = (state, action) => {
switch(action.type) {
case "CREATE COMMENT":
return {
...state,
comments: [
...state.comments,
action.newComment
]
};
case "UPDATE COMMENT":
for (let i = 0; i < state.comments.length; i++) {
// find the comment in state
if (state.comments[i].commentId === action.newComment.commentId) {
let newComment = makeDeepCopy(state.comments[i]);
newComment.htmlCommentText = action.newComment.htmlCommentText; // update comment text
newComment.rawCommentText = action.newComment.rawCommentText;
return {
...state,
comments: Object.assign(
[],
state.comments,
{ [i]: newComment }
)
}; // keep the rest of state.comments, but replace comment at index i with newComment
}
}
break;
case "DELETE COMMENT":
for (let i = 0; i < state.comments.length; i++) {
// find the comment in state by ID
if (state.comments[i].commentId === action.commentId) {
return {
...state,
comments: state.comments.filter(comment => action.commentId !== comment.commentId)
};
}
}
break;
default:
throw new Error(); // default should never be called
}
}

export {
reducer
}

0 comments on commit 596ff0c

Please sign in to comment.