-
Notifications
You must be signed in to change notification settings - Fork 0
β‘ Bolt: [performance improvement] fix TalksFilterBar debounce #143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,7 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "use client"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { usePathname, useRouter, useSearchParams } from "next/navigation"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useCallback, useEffect, useState, useTransition } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useCallback, useEffect, useState, useTransition, useRef } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { motion } from "framer-motion"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface TalksFilterBarProps { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -22,6 +22,8 @@ export default function TalksFilterBar({ tracks, year: _year }: TalksFilterBarPr | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [selectedTrack, setSelectedTrack] = useState<string>(searchParams.get("track") || ""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [searchQuery, setSearchQuery] = useState<string>(searchParams.get("q") || ""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+25
to
+26
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π§© Analysis chainπ Script executed: find . -name "TalksFilterBar.tsx" -type fRepository: anyulled/devbcn-nextjs Length of output: 104 π Script executed: cat -n components/layout/TalksFilterBar.tsxRepository: anyulled/devbcn-nextjs Length of output: 6629 Add unmount cleanup for the debounced timer.
Proposed fix const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
+ useEffect(() => {
+ return () => {
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current);
+ timeoutRef.current = null;
+ }
+ };
+ }, []);
+
// Update state when URL changes
useEffect(() => {π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Update state when URL changes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setSelectedTrack(searchParams.get("track") || ""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -60,11 +62,15 @@ export default function TalksFilterBar({ tracks, year: _year }: TalksFilterBarPr | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const newQuery = e.target.value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setSearchQuery(newQuery); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (timeoutRef.current) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clearTimeout(timeoutRef.current); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Debounce the URL update for search | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const timeoutId = setTimeout(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeoutRef.current = setTimeout(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| updateFilters(selectedTrack, newQuery); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+71
to
72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. Stale track in debounce The debounced callback in handleSearchChange calls updateFilters(selectedTrack, newQuery) with selectedTrack captured at the time of typing. If the user clicks a track within the 300ms window, the pending timeout can later push a URL with the old track, undoing the userβs track selection. Agent Prompt
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, 300); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+66
to
73
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π§© Analysis chainπ Script executed: #!/bin/bash
# Verify stale-callback risk patterns in the current file.
rg -n -C3 'const handleTrackClick|setTimeout\(|updateFilters\(selectedTrack,\s*newQuery\)|clearTimeout\(timeoutRef\.current\)' components/layout/TalksFilterBar.tsxRepository: anyulled/devbcn-nextjs Length of output: 608 π Script executed: cat -n components/layout/TalksFilterBar.tsxRepository: anyulled/devbcn-nextjs Length of output: 6629 Clear pending search timeout when track selection changes. When a user types then clicks a track before the 300ms debounce fires, the pending callback still executes with the captured stale Proposed fix const handleTrackClick = (track: string) => {
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current);
+ timeoutRef.current = null;
+ }
const newTrack = track === selectedTrack ? "" : track;
setSelectedTrack(newTrack);
updateFilters(newTrack, searchQuery);
};
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newQuery = e.target.value;
setSearchQuery(newQuery);
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
+ timeoutRef.current = null;
}
// Debounce the URL update for search
timeoutRef.current = setTimeout(() => {
updateFilters(selectedTrack, newQuery);
+ timeoutRef.current = null;
}, 300);
};π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return () => clearTimeout(timeoutId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
62
to
74
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current implementation using A more robust approach is to use a
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
useRefhook is no longer necessary if the debounce logic is moved to auseEffecthook as suggested below to handle the side effect more robustly.