From 987f78ac25af119796c6f3830a61aafcabeb2dc1 Mon Sep 17 00:00:00 2001
From: nsfisis
Date: Fri, 22 Aug 2025 23:17:09 +0900
Subject: fix(frontend): wrong optimistic update
---
frontend/src/components/ArticleItem.tsx | 38 +++++++++++----------------------
frontend/src/components/ArticleList.tsx | 28 ++++++++++++++++++++----
frontend/src/pages/ReadArticles.tsx | 4 +++-
frontend/src/pages/UnreadArticles.tsx | 4 +++-
4 files changed, 43 insertions(+), 31 deletions(-)
(limited to 'frontend/src')
diff --git a/frontend/src/components/ArticleItem.tsx b/frontend/src/components/ArticleItem.tsx
index faa86fe..4942518 100644
--- a/frontend/src/components/ArticleItem.tsx
+++ b/frontend/src/components/ArticleItem.tsx
@@ -1,6 +1,5 @@
import { faCheck, faCircle } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { useOptimistic } from "react";
import { useMutation } from "urql";
import type {
GetReadArticlesQuery,
@@ -18,27 +17,19 @@ type Article = NonNullable<
interface Props {
article: Article;
+ onReadChange?: (articleId: string, isRead: boolean) => void;
}
-export function ArticleItem({ article }: Props) {
+export function ArticleItem({ article, onReadChange }: Props) {
const [, markArticleRead] = useMutation(MarkArticleReadDocument);
const [, markArticleUnread] = useMutation(MarkArticleUnreadDocument);
- const [optimisticArticle, setOptimisticArticle] = useOptimistic(
- article,
- (currentArticle, newReadState: boolean) => ({
- ...currentArticle,
- isRead: newReadState,
- }),
- );
-
const handleToggleRead = async (
articleId: string,
isCurrentlyRead: boolean,
) => {
const newReadState = !isCurrentlyRead;
-
- setOptimisticArticle(newReadState);
+ onReadChange?.(articleId, newReadState);
if (isCurrentlyRead) {
await markArticleUnread({ id: articleId });
@@ -50,9 +41,8 @@ export function ArticleItem({ article }: Props) {
const handleArticleClick = async (article: Article) => {
// Open article in new tab and mark as read if it's unread
window.open(article.url, "_blank", "noreferrer");
- if (!optimisticArticle.isRead) {
- setOptimisticArticle(true);
-
+ if (!article.isRead) {
+ onReadChange?.(article.id, true);
await markArticleRead({ id: article.id });
}
};
@@ -60,38 +50,36 @@ export function ArticleItem({ article }: Props) {
return (
diff --git a/frontend/src/components/ArticleList.tsx b/frontend/src/components/ArticleList.tsx
index 2ea94f0..574f529 100644
--- a/frontend/src/components/ArticleList.tsx
+++ b/frontend/src/components/ArticleList.tsx
@@ -1,3 +1,4 @@
+import { useState } from "react";
import type {
GetReadArticlesQuery,
GetUnreadArticlesQuery,
@@ -9,17 +10,32 @@ interface Props {
| GetUnreadArticlesQuery["unreadArticles"]
| GetReadArticlesQuery["readArticles"]
>;
+ isReadView?: boolean;
}
-export function ArticleList({ articles }: Props) {
- if (articles.length === 0) {
+export function ArticleList({ articles, isReadView }: Props) {
+ const [hiddenArticleIds, setHiddenArticleIds] = useState
>(
+ new Set(),
+ );
+
+ const handleArticleReadChange = (articleId: string, isRead: boolean) => {
+ if (isReadView !== isRead) {
+ setHiddenArticleIds((prev) => new Set(prev).add(articleId));
+ }
+ };
+
+ const visibleArticles = articles.filter(
+ (article) => !hiddenArticleIds.has(article.id),
+ );
+
+ if (visibleArticles.length === 0) {
return (
No articles found.
);
}
// Group articles by feed
- const articlesByFeed = articles.reduce(
+ const articlesByFeed = visibleArticles.reduce(
(acc, article) => {
const feedId = article.feed.id;
if (!acc[feedId]) {
@@ -50,7 +66,11 @@ export function ArticleList({ articles }: Props) {
{feedArticles.map((article) => (
-
+
))}
diff --git a/frontend/src/pages/ReadArticles.tsx b/frontend/src/pages/ReadArticles.tsx
index 44ae834..74c1f5c 100644
--- a/frontend/src/pages/ReadArticles.tsx
+++ b/frontend/src/pages/ReadArticles.tsx
@@ -26,7 +26,9 @@ export function ReadArticles() {
)}
- {data?.readArticles && }
+ {data?.readArticles && (
+
+ )}
);
}
diff --git a/frontend/src/pages/UnreadArticles.tsx b/frontend/src/pages/UnreadArticles.tsx
index f82d4dc..45ae0f9 100644
--- a/frontend/src/pages/UnreadArticles.tsx
+++ b/frontend/src/pages/UnreadArticles.tsx
@@ -26,7 +26,9 @@ export function UnreadArticles() {
)}
- {data?.unreadArticles && }
+ {data?.unreadArticles && (
+
+ )}
);
}
--
cgit v1.2.3-70-g09d2