perf(home): stop popular threads rerenders after load

This commit is contained in:
Tommaso Casaburi
2026-04-19 15:01:27 +07:00
parent 508fffe5d6
commit 4b06ac8c9a
7 changed files with 249 additions and 17 deletions
@@ -82,4 +82,19 @@ describe('browser hooks', () => {
expect(latestValue).toBe(1_704_067_230);
});
it('can leave the current time frozen without scheduling updates', () => {
vi.useFakeTimers();
vi.setSystemTime(new Date('2024-01-01T00:00:00Z'));
expect(renderHookValue(() => useCurrentTime(false))).toBe(1_704_067_200);
act(() => {
vi.setSystemTime(new Date('2024-01-01T00:01:00Z'));
vi.advanceTimersByTime(60_000);
});
expect(latestValue).toBe(1_704_067_200);
expect(vi.getTimerCount()).toBe(0);
});
});
+5 -1
View File
@@ -8,10 +8,14 @@ import { useState, useEffect } from 'react';
* For visual updates like blinking animations, CSS handles that independently.
* This hook is for time-based calculations that don't need millisecond precision.
*/
export const useCurrentTime = (updateIntervalSeconds = 60) => {
export const useCurrentTime = (updateIntervalSeconds: number | false = 60) => {
const [currentTime, setCurrentTime] = useState(() => Date.now() / 1000);
useEffect(() => {
if (updateIntervalSeconds === false) {
return;
}
// Update periodically
const intervalId = setInterval(() => {
setCurrentTime(Date.now() / 1000);
+11 -2
View File
@@ -58,6 +58,10 @@ function shuffleBoardAddresses(boardAddresses: string[]): string[] {
return shuffledBoardAddresses;
}
function getPopularPostsInputKey(communityAddresses: string[]): string {
return [...communityAddresses].sort().join(',');
}
function getPopularPostsCacheEntry(inputKey: string, communityAddresses: string[]): PopularPostsCacheEntry {
const cachedEntry = popularPostsCacheByInputKey.get(inputKey);
if (cachedEntry) {
@@ -73,6 +77,11 @@ function getPopularPostsCacheEntry(inputKey: string, communityAddresses: string[
return cacheEntry;
}
export function getRevealedPopularPosts(communityAddresses: string[]): Comment[] | undefined {
const cacheEntry = popularPostsCacheByInputKey.get(getPopularPostsInputKey(communityAddresses));
return cacheEntry?.revealed ? cacheEntry.posts : undefined;
}
export function clearPopularPostsCacheForTest() {
popularPostsCacheByInputKey.clear();
}
@@ -86,10 +95,10 @@ export function clearPopularPostsCacheForTest() {
* the board filter, so threads never disappear during background loads.
*/
const usePopularPosts = (communities: Array<Community | undefined>, communityAddresses: string[]) => {
const inputKey = [...communityAddresses].sort().join(',');
const inputKey = getPopularPostsInputKey(communityAddresses);
const cacheEntry = getPopularPostsCacheEntry(inputKey, communityAddresses);
const currentTime = useCurrentTime(cacheEntry.revealed ? 300 : 5);
const currentTime = useCurrentTime(cacheEntry.revealed ? false : 5);
const nowSeconds = Math.floor(currentTime);
const loadingStartTimestamps = useCommunitiesLoadingStartTimestamps(communityAddresses);