add reddit features to reviewdb#4216
Conversation
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request implements a voting system for reviews, allowing users to upvote or downvote content. Key changes include the addition of a VoteButton component, new API endpoints for managing votes, and state management within the ReviewComponent to track scores and user interactions. The review feedback focuses on improving the robustness of the state management by using useEffect to synchronize local state with props, implementing a loading state to prevent race conditions during concurrent voting requests, and utilizing functional state updates to ensure score accuracy.
| @@ -27,7 +27,7 @@ import { findCssClassesLazy } from "@webpack"; | |||
| import { Alerts, IconUtils, Parser, Timestamp, useState } from "@webpack/common"; | |||
There was a problem hiding this comment.
Add useEffect to the imports from @webpack/common to allow syncing the local state with props when they change (e.g., after a refetch).
| import { Alerts, IconUtils, Parser, Timestamp, useState } from "@webpack/common"; | |
| import { Alerts, IconUtils, Parser, Timestamp, useEffect, useState } from "@webpack/common"; |
| const [localVote, setLocalVote] = useState<boolean | null>(review.userVote ?? null); | ||
| const [score, setScore] = useState(review.score ?? 0); |
There was a problem hiding this comment.
Introduce a loading state to prevent concurrent voting requests and use useEffect to keep the local state in sync with the review prop. Since useState only initializes once, the local score and localVote would otherwise become stale if the parent component refetches data.
const [localVote, setLocalVote] = useState<boolean | null>(review.userVote ?? null);
const [score, setScore] = useState(review.score ?? 0);
const [isVoting, setIsVoting] = useState(false);
useEffect(() => {
setLocalVote(review.userVote ?? null);
setScore(review.score ?? 0);
}, [review.userVote, review.score]);
| async function submitVote(isUpvote: boolean) { | ||
| if (review.sender.discordID === Auth.user?.discordID) { | ||
| return showToast("You cannot vote on your own review."); | ||
| } | ||
|
|
||
| if (localVote === isUpvote) { | ||
| return showToast(`You already ${isUpvote ? "upvoted" : "downvoted"} this review.`); | ||
| } | ||
|
|
||
| if (await voteReview(review.id, isUpvote)) { | ||
| const delta = localVote == null | ||
| ? isUpvote ? 1 : -1 | ||
| : isUpvote ? 2 : -2; | ||
|
|
||
| setLocalVote(isUpvote); | ||
| setScore(score + delta); | ||
| } | ||
| } |
There was a problem hiding this comment.
Implement the isVoting check to prevent race conditions from multiple clicks. Additionally, use a functional update for setScore to ensure the score is updated correctly based on the most recent state, and wrap the API call in a try...finally block to ensure the loading state is reset even if the request fails.
async function submitVote(isUpvote: boolean) {
if (isVoting) return;
if (review.sender.discordID === Auth.user?.discordID) {
return showToast("You cannot vote on your own review.");
}
if (localVote === isUpvote) {
return showToast(`You already ${isUpvote ? "upvoted" : "downvoted"} this review.`);
}
setIsVoting(true);
try {
if (await voteReview(review.id, isUpvote)) {
const delta = localVote == null
? isUpvote ? 1 : -1
: isUpvote ? 2 : -2;
setLocalVote(isUpvote);
setScore(s => s + delta);
}
} finally {
setIsVoting(false);
}
}
|
@copilot fix whatever gemini said |
|
@copilot retard fix the issues gemini said |
|
sugoooooi I think this should be merged |
|
@gemini FIX: review merge |
|
I have reviewed the changes for adding voting functionality to ReviewDB. The implementation correctly introduces the One minor improvement for maintainability: In |
No description provided.