Skip to content

Commit 3ebb154

Browse files
committed
feat: implement readPostIdSet for optimized read post management
1 parent 8c28abe commit 3ebb154

File tree

2 files changed

+41
-25
lines changed

2 files changed

+41
-25
lines changed

src/components/List/ListComponent.tsx

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,20 @@ export function ListComponent<T extends any>(props: ListComponentPropsType<T>) {
4444
limit = MAX_ITEMS_PER_CARD,
4545
} = props
4646

47-
const { readPostIds } = useReadPosts()
4847
const { showReadPosts } = useUserPreferences()
48+
const readPostIdSet = useReadPosts((state) => state.readPostIdSet)
4949

5050
const filteredItems = useMemo(() => {
51-
if (!items || items.length === 0) return []
52-
if (showReadPosts) return items
53-
const readSet = new Set(readPostIds)
54-
return items.filter((item: any) => !readSet.has(item.id))
55-
}, [items, readPostIds, showReadPosts])
51+
if (!items || items.length === 0) {
52+
return []
53+
}
54+
55+
if (showReadPosts) {
56+
return items
57+
}
58+
59+
return items.filter((item: any) => !readPostIdSet.has(item.id))
60+
}, [items, readPostIdSet, showReadPosts])
5661

5762
const sortedData = useMemo(() => {
5863
if (!filteredItems || filteredItems.length == 0) return []
@@ -71,23 +76,14 @@ export function ListComponent<T extends any>(props: ListComponentPropsType<T>) {
7176
return result
7277
}, [sortBy, sortFn, filteredItems])
7378

74-
const readSet = useMemo(() => new Set(readPostIds), [readPostIds])
75-
7679
const enrichedItems = useMemo(() => {
7780
if (!sortedData || sortedData.length === 0) {
7881
return []
7982
}
8083

8184
try {
8285
return sortedData.slice(0, limit).map((item, index) => {
83-
const isRead = readSet.has((item as any).id)
84-
const itemNode = isRead ? (
85-
<div key={(item as any).id} className="readPostWrapper" aria-label="Read">
86-
{renderItem(item, index)}
87-
</div>
88-
) : (
89-
renderItem(item, index)
90-
)
86+
const itemNode = renderItem(item, index)
9187
let content: ReactNode[] = [itemNode]
9288
if (header && index === 0) {
9389
content.unshift(header)
@@ -98,7 +94,7 @@ export function ListComponent<T extends any>(props: ListComponentPropsType<T>) {
9894
} catch (e) {
9995
return []
10096
}
101-
}, [sortedData, header, renderItem, limit, readSet])
97+
}, [sortedData, header, renderItem, limit])
10298

10399
if (isLoading) {
104100
return <Placeholders placeholder={placeholder} />
@@ -120,7 +116,9 @@ export function ListComponent<T extends any>(props: ListComponentPropsType<T>) {
120116
<div className="centerMessageWrapper cardLoading">
121117
<div className="centerMessage errorMsg">
122118
<span className="centerMessageIcon"></span>
123-
<p><b>You're all caught up!</b></p>
119+
<p>
120+
<b>You're all caught up!</b>
121+
</p>
124122
<p className="centerMessageSubtext">Check back later for fresh content.</p>
125123
</div>
126124
</div>

src/stores/readPosts.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const MAX_READ_POST_IDS = 5000
55

66
type ReadPostsStore = {
77
readPostIds: string[]
8+
readPostIdSet: Set<string>
89
markAsRead: (postId: string) => void
910
markAsUnread: (postId: string) => void
1011
}
@@ -13,7 +14,7 @@ export const useReadPosts = create<ReadPostsStore>()(
1314
persist(
1415
(set) => ({
1516
readPostIds: [],
16-
17+
readPostIdSet: new Set(),
1718
markAsRead: (postId) =>
1819
set((state) => {
1920
if (state.readPostIds.includes(postId)) return state
@@ -23,14 +24,31 @@ export const useReadPosts = create<ReadPostsStore>()(
2324
? [...state.readPostIds.slice(1), postId]
2425
: [...state.readPostIds, postId]
2526

26-
return { readPostIds: next }
27+
const nextSet = new Set(state.readPostIdSet)
28+
nextSet.add(postId)
29+
30+
return { readPostIds: next, readPostIdSet: nextSet }
2731
}),
2832

2933
markAsUnread: (postId) =>
30-
set((state) => ({
31-
readPostIds: state.readPostIds.filter((id) => id !== postId),
32-
})),
34+
set((state) => {
35+
if (!state.readPostIds.includes(postId)) return state
36+
37+
const next = state.readPostIds.filter((id) => id !== postId)
38+
const nextSet = new Set(state.readPostIdSet)
39+
nextSet.delete(postId)
40+
41+
return { readPostIds: next, readPostIdSet: nextSet }
42+
}),
3343
}),
34-
{ name: 'read_post_ids' }
44+
{
45+
name: 'read_post_ids_storage',
46+
partialize: (state) => ({ readPostIds: state.readPostIds }),
47+
onRehydrateStorage: () => (state) => {
48+
if (state) {
49+
state.readPostIdSet = new Set(state.readPostIds)
50+
}
51+
},
52+
}
3553
)
36-
)
54+
)

0 commit comments

Comments
 (0)