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 { create } from 'zustand';
import { persist } from 'zustand/middleware'; import { persist } from 'zustand/middleware';
import { Comment } from '@plebbit/plebbit-react-hooks';
import { getCommentMediaInfo, getHasThumbnail } from '../lib/utils/media-utils';
interface FilterItem { interface FilterItem {
text: string; text: string;
@@ -16,15 +18,21 @@ interface CatalogFiltersStore {
filterText: string; filterText: string;
setFilterText: (value: string) => void; setFilterText: (value: string) => void;
filterItems: FilterItem[]; filterItems: FilterItem[];
setFilterItems: (items: FilterItem[]) => void; // New method to set all filter items at once setFilterItems: (items: FilterItem[]) => void;
saveAndApplyFilters: (items: FilterItem[]) => void; // Updated to accept items saveAndApplyFilters: (items: FilterItem[]) => void;
filter: ((comment: Comment) => boolean) | undefined;
updateFilter: () => void;
initializeFilter: () => void;
} }
const useCatalogFiltersStore = create( const useCatalogFiltersStore = create(
persist<CatalogFiltersStore>( persist<CatalogFiltersStore>(
(set) => ({ (set, get) => ({
showTextOnlyThreads: false, showTextOnlyThreads: false,
setShowTextOnlyThreads: (value: boolean) => set({ showTextOnlyThreads: value }), setShowTextOnlyThreads: (value: boolean) => {
set({ showTextOnlyThreads: value });
get().updateFilter();
},
showAdultBoards: false, showAdultBoards: false,
setShowAdultBoards: (value: boolean) => set({ showAdultBoards: value }), setShowAdultBoards: (value: boolean) => set({ showAdultBoards: value }),
showGoreBoards: false, showGoreBoards: false,
@@ -39,12 +47,44 @@ const useCatalogFiltersStore = create(
saveAndApplyFilters: (items: FilterItem[]) => { saveAndApplyFilters: (items: FilterItem[]) => {
const nonEmptyItems = items.filter((item) => item.text.trim() !== ''); const nonEmptyItems = items.filter((item) => item.text.trim() !== '');
set({ filterItems: nonEmptyItems }); 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', name: 'catalog-filters-storage',
onRehydrateStorage: () => (state) => {
if (state) {
state.updateFilter();
}
},
}, },
), ),
); );
useCatalogFiltersStore.getState().updateFilter();
export default useCatalogFiltersStore; 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 { useLocation, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next'; 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 { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
import { getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils';
import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils'; import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils';
import useCatalogFeedRows from '../../hooks/use-catalog-feed-rows'; import useCatalogFeedRows from '../../hooks/use-catalog-feed-rows';
import useDefaultSubplebbits from '../../hooks/use-default-subplebbits'; import useDefaultSubplebbits from '../../hooks/use-default-subplebbits';
@@ -28,7 +27,7 @@ const Catalog = () => {
const isInAllView = isAllView(location.pathname, useParams()); const isInAllView = isAllView(location.pathname, useParams());
const defaultSubplebbits = useDefaultSubplebbits(); const defaultSubplebbits = useDefaultSubplebbits();
const { showAdultBoards, showGoreBoards } = useCatalogFiltersStore(); const { filter, showAdultBoards, showGoreBoards } = useCatalogFiltersStore();
const account = useAccount(); const account = useAccount();
const subscriptions = account?.subscriptions; const subscriptions = account?.subscriptions;
@@ -57,27 +56,6 @@ const Catalog = () => {
return [subplebbitAddress]; return [subplebbitAddress];
}, [isInAllView, isInSubscriptionsView, subplebbitAddress, defaultSubplebbits, subscriptions, showAdultBoards, showGoreBoards]); }, [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 { imageSize } = useCatalogStyleStore();
const columnWidth = imageSize === 'Large' ? 270 : 180; const columnWidth = imageSize === 'Large' ? 270 : 180;
@@ -87,16 +65,20 @@ const Catalog = () => {
const { timeFilterSeconds } = useTimeFilter(); const { timeFilterSeconds } = useTimeFilter();
const { sortType } = useSortingStore(); const { sortType } = useSortingStore();
const feedOptions: any = { const feedOptions = useMemo(() => {
subplebbitAddresses, const options: any = {
sortType, subplebbitAddresses,
postsPerPage: isInAllView || isInSubscriptionsView ? 10 : postsPerPage, sortType,
filter, postsPerPage: isInAllView || isInSubscriptionsView ? 10 : postsPerPage,
}; filter,
};
if (isInAllView || isInSubscriptionsView) { if (isInAllView || isInSubscriptionsView) {
feedOptions.newerThan = timeFilterSeconds; options.newerThan = timeFilterSeconds;
} }
return options;
}, [subplebbitAddresses, sortType, isInAllView, isInSubscriptionsView, postsPerPage, timeFilterSeconds, filter]);
const { feed, hasMore, loadMore, reset } = useFeed(feedOptions); const { feed, hasMore, loadMore, reset } = useFeed(feedOptions);