mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
perf: implement LRU-cached persistent feed mounting to eliminate Virtuoso flash
Keep Board/Catalog feeds mounted outside React Router's control to prevent Virtuoso from remounting when navigating to/from post pages. The feed is hidden via CSS when viewing posts and shown again when returning, eliminating the visible flash/displacement that occurred during scroll restoration. - Add FeedCacheContainer to manage LRU cache of 2 feeds - Modify Board/Catalog to accept cache props and visibility state - Add route utilities for feed/post route detection
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
export interface CachedFeed {
|
||||
key: string;
|
||||
type: 'board' | 'catalog';
|
||||
lastAccessed: number;
|
||||
}
|
||||
|
||||
interface FeedCacheState {
|
||||
cachedFeeds: CachedFeed[];
|
||||
maxCacheSize: number;
|
||||
accessFeed: (key: string, type: 'board' | 'catalog') => void;
|
||||
removeFeed: (key: string) => void;
|
||||
isFeedCached: (key: string) => boolean;
|
||||
}
|
||||
|
||||
const useFeedCacheStore = create<FeedCacheState>((set, get) => ({
|
||||
cachedFeeds: [],
|
||||
maxCacheSize: 2,
|
||||
|
||||
accessFeed: (key: string, type: 'board' | 'catalog') => {
|
||||
const { cachedFeeds, maxCacheSize } = get();
|
||||
const now = Date.now();
|
||||
const existingIndex = cachedFeeds.findIndex((feed) => feed.key === key);
|
||||
|
||||
if (existingIndex !== -1) {
|
||||
const updatedFeeds = [...cachedFeeds];
|
||||
updatedFeeds[existingIndex] = { ...updatedFeeds[existingIndex], lastAccessed: now };
|
||||
set({ cachedFeeds: updatedFeeds });
|
||||
} else {
|
||||
const newFeed: CachedFeed = { key, type, lastAccessed: now };
|
||||
let updatedFeeds = [...cachedFeeds, newFeed];
|
||||
|
||||
if (updatedFeeds.length > maxCacheSize) {
|
||||
updatedFeeds.sort((a, b) => a.lastAccessed - b.lastAccessed);
|
||||
updatedFeeds = updatedFeeds.slice(1);
|
||||
}
|
||||
|
||||
set({ cachedFeeds: updatedFeeds });
|
||||
}
|
||||
},
|
||||
|
||||
removeFeed: (key: string) => {
|
||||
const { cachedFeeds } = get();
|
||||
set({ cachedFeeds: cachedFeeds.filter((feed) => feed.key !== key) });
|
||||
},
|
||||
|
||||
isFeedCached: (key: string) => {
|
||||
const { cachedFeeds } = get();
|
||||
return cachedFeeds.some((feed) => feed.key === key);
|
||||
},
|
||||
}));
|
||||
|
||||
export default useFeedCacheStore;
|
||||
Reference in New Issue
Block a user