use zustand memoization for catalog filters, it fixes the useFeed bug with performance

This commit is contained in:
Tom (plebeius.eth)
2024-09-10 18:20:24 +02:00
parent e068db9743
commit d45cc8b126
2 changed files with 60 additions and 38 deletions
+44 -4
View File
@@ -1,5 +1,7 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { Comment } from '@plebbit/plebbit-react-hooks';
import { getCommentMediaInfo, getHasThumbnail } from '../lib/utils/media-utils';
interface FilterItem {
text: string;
@@ -16,15 +18,21 @@ interface CatalogFiltersStore {
filterText: string;
setFilterText: (value: string) => void;
filterItems: FilterItem[];
setFilterItems: (items: FilterItem[]) => void; // New method to set all filter items at once
saveAndApplyFilters: (items: FilterItem[]) => void; // Updated to accept items
setFilterItems: (items: FilterItem[]) => void;
saveAndApplyFilters: (items: FilterItem[]) => void;
filter: ((comment: Comment) => boolean) | undefined;
updateFilter: () => void;
initializeFilter: () => void;
}
const useCatalogFiltersStore = create(
persist<CatalogFiltersStore>(
(set) => ({
(set, get) => ({
showTextOnlyThreads: false,
setShowTextOnlyThreads: (value: boolean) => set({ showTextOnlyThreads: value }),
setShowTextOnlyThreads: (value: boolean) => {
set({ showTextOnlyThreads: value });
get().updateFilter();
},
showAdultBoards: false,
setShowAdultBoards: (value: boolean) => set({ showAdultBoards: value }),
showGoreBoards: false,
@@ -39,12 +47,44 @@ const useCatalogFiltersStore = create(
saveAndApplyFilters: (items: FilterItem[]) => {
const nonEmptyItems = items.filter((item) => item.text.trim() !== '');
set({ filterItems: nonEmptyItems });
get().updateFilter();
},
filter: undefined,
updateFilter: () =>
set((state) => ({
filter: (comment: Comment) => {
const { showTextOnlyThreads, filterItems } = state;
if (!showTextOnlyThreads && !getHasThumbnail(getCommentMediaInfo(comment), comment?.link)) {
return false;
}
const title = comment?.title?.toLowerCase() || '';
const content = comment?.content?.toLowerCase() || '';
return !filterItems
.filter((item) => item.enabled)
.some((item) => {
const text = item.text.toLowerCase();
return title.includes(text) || content.includes(text);
});
},
})),
initializeFilter: () => {
const { updateFilter } = get();
updateFilter();
},
}),
{
name: 'catalog-filters-storage',
onRehydrateStorage: () => (state) => {
if (state) {
state.updateFilter();
}
},
},
),
);
useCatalogFiltersStore.getState().updateFilter();
export default useCatalogFiltersStore;
+16 -34
View File
@@ -1,9 +1,8 @@
import { useEffect, useMemo, useRef, useCallback } from 'react';
import { useEffect, useMemo, useRef } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Comment, useAccount, useFeed, useSubplebbit, useBlock } from '@plebbit/plebbit-react-hooks';
import { useAccount, useFeed, useSubplebbit, useBlock } from '@plebbit/plebbit-react-hooks';
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
import { getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils';
import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils';
import useCatalogFeedRows from '../../hooks/use-catalog-feed-rows';
import useDefaultSubplebbits from '../../hooks/use-default-subplebbits';
@@ -28,7 +27,7 @@ const Catalog = () => {
const isInAllView = isAllView(location.pathname, useParams());
const defaultSubplebbits = useDefaultSubplebbits();
const { showAdultBoards, showGoreBoards } = useCatalogFiltersStore();
const { filter, showAdultBoards, showGoreBoards } = useCatalogFiltersStore();
const account = useAccount();
const subscriptions = account?.subscriptions;
@@ -57,27 +56,6 @@ const Catalog = () => {
return [subplebbitAddress];
}, [isInAllView, isInSubscriptionsView, subplebbitAddress, defaultSubplebbits, subscriptions, showAdultBoards, showGoreBoards]);
const { showTextOnlyThreads, filterItems } = useCatalogFiltersStore();
const filter = useCallback(
(comment: Comment) => {
if (!showTextOnlyThreads && !getHasThumbnail(getCommentMediaInfo(comment), comment?.link)) {
return false;
}
const title = comment?.title?.toLowerCase() || '';
const content = comment?.content?.toLowerCase() || '';
return !filterItems
.filter((item) => item.enabled)
.some((item) => {
const text = item.text.toLowerCase();
return title.includes(text) || content.includes(text);
});
},
[filterItems, showTextOnlyThreads],
);
const { imageSize } = useCatalogStyleStore();
const columnWidth = imageSize === 'Large' ? 270 : 180;
@@ -87,16 +65,20 @@ const Catalog = () => {
const { timeFilterSeconds } = useTimeFilter();
const { sortType } = useSortingStore();
const feedOptions: any = {
subplebbitAddresses,
sortType,
postsPerPage: isInAllView || isInSubscriptionsView ? 10 : postsPerPage,
filter,
};
const feedOptions = useMemo(() => {
const options: any = {
subplebbitAddresses,
sortType,
postsPerPage: isInAllView || isInSubscriptionsView ? 10 : postsPerPage,
filter,
};
if (isInAllView || isInSubscriptionsView) {
feedOptions.newerThan = timeFilterSeconds;
}
if (isInAllView || isInSubscriptionsView) {
options.newerThan = timeFilterSeconds;
}
return options;
}, [subplebbitAddresses, sortType, isInAllView, isInSubscriptionsView, postsPerPage, timeFilterSeconds, filter]);
const { feed, hasMore, loadMore, reset } = useFeed(feedOptions);