Defer sidebar queries until feed loads and sidebar is visible
- Add `enabled` parameter to `useTrendingTags` and `useLatestAccounts` hooks - RightSidebar now detects xl breakpoint visibility with matchMedia - Sidebar queries only fire after the feed finishes its initial fetch - On smaller screens where the sidebar is hidden, queries are skipped entirely - Gives the feed full relay bandwidth priority on page load Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
@@ -6,7 +6,24 @@ import { useTrendingTags, useLatestAccounts } from '@/hooks/useTrending';
|
||||
import { genUserName } from '@/lib/genUserName';
|
||||
import { NSchema as n } from '@nostrify/nostrify';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { useMemo } from 'react';
|
||||
import { useMemo, useState, useEffect } from 'react';
|
||||
import { useIsFetching } from '@tanstack/react-query';
|
||||
|
||||
const XL_BREAKPOINT = 1280;
|
||||
|
||||
/** Returns true when the viewport is at least the xl breakpoint (1280px). */
|
||||
function useIsXl(): boolean {
|
||||
const [isXl, setIsXl] = useState(window.innerWidth >= XL_BREAKPOINT);
|
||||
|
||||
useEffect(() => {
|
||||
const mql = window.matchMedia(`(min-width: ${XL_BREAKPOINT}px)`);
|
||||
const onChange = () => setIsXl(mql.matches);
|
||||
mql.addEventListener('change', onChange);
|
||||
return () => mql.removeEventListener('change', onChange);
|
||||
}, []);
|
||||
|
||||
return isXl;
|
||||
}
|
||||
|
||||
/** Small sparkline SVG for trending tags. */
|
||||
function TrendSparkline() {
|
||||
@@ -36,8 +53,27 @@ function TrendSparkline() {
|
||||
}
|
||||
|
||||
export function RightSidebar() {
|
||||
const { data: trendingTags, isLoading: tagsLoading } = useTrendingTags();
|
||||
const { data: latestAccounts, isLoading: accountsLoading } = useLatestAccounts();
|
||||
const isXl = useIsXl();
|
||||
|
||||
// Only start sidebar queries once the feed has finished its initial fetch.
|
||||
// Track: feed must start fetching first, then finish, before we enable sidebar queries.
|
||||
const feedFetching = useIsFetching({ queryKey: ['feed'] });
|
||||
const [feedStarted, setFeedStarted] = useState(false);
|
||||
const [feedHasLoaded, setFeedHasLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!feedStarted && feedFetching > 0) {
|
||||
setFeedStarted(true);
|
||||
}
|
||||
if (feedStarted && !feedHasLoaded && feedFetching === 0) {
|
||||
setFeedHasLoaded(true);
|
||||
}
|
||||
}, [feedFetching, feedStarted, feedHasLoaded]);
|
||||
|
||||
const sidebarEnabled = isXl && feedHasLoaded;
|
||||
|
||||
const { data: trendingTags, isLoading: tagsLoading } = useTrendingTags(sidebarEnabled);
|
||||
const { data: latestAccounts, isLoading: accountsLoading } = useLatestAccounts(sidebarEnabled);
|
||||
|
||||
return (
|
||||
<aside className="w-[340px] shrink-0 hidden xl:flex flex-col sticky top-0 h-screen overflow-y-auto pt-6 pb-3 px-6">
|
||||
|
||||
@@ -8,7 +8,7 @@ export interface TrendingTag {
|
||||
}
|
||||
|
||||
/** Extracts trending hashtags from recent notes. */
|
||||
export function useTrendingTags() {
|
||||
export function useTrendingTags(enabled = true) {
|
||||
const { nostr } = useNostr();
|
||||
|
||||
return useQuery<TrendingTag[]>({
|
||||
@@ -39,12 +39,13 @@ export function useTrendingTags() {
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.slice(0, 5);
|
||||
},
|
||||
enabled,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
/** Fetches the latest kind 0 profiles seen on the relay. */
|
||||
export function useLatestAccounts() {
|
||||
export function useLatestAccounts(enabled = true) {
|
||||
const { nostr } = useNostr();
|
||||
|
||||
return useQuery<NostrEvent[]>({
|
||||
@@ -56,6 +57,7 @@ export function useLatestAccounts() {
|
||||
);
|
||||
return events.sort((a, b) => b.created_at - a.created_at).slice(0, 5);
|
||||
},
|
||||
enabled,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user