feat: add debounced search for pool filtering on Explore page#87
feat: add debounced search for pool filtering on Explore page#87Atharva0506 wants to merge 2 commits into
Conversation
WalkthroughThis PR introduces a reusable ChangesDebounce Search Refactoring
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/app/explorePools/page.tsx (1)
563-576: 🧹 Nitpick | 🔵 TrivialCompute
searchLoweronce per memo, not once per pool.At Line 566,
debouncedSearchQuery.toLowerCase()is recalculated for every item inpools. Move it outside the filter callback to reduce repeated work on large lists.♻️ Suggested refactor
- const filteredPools = useMemo( - (): Pool[] => - pools.filter((pool: Pool) => { - const searchLower = debouncedSearchQuery.toLowerCase(); + const filteredPools = useMemo((): Pool[] => { + const searchLower = debouncedSearchQuery.toLowerCase(); + return pools.filter((pool: Pool) => { const priceFeedName = getPriceFeedName(pool.priceFeedAddress, pool.chainId); return ( pool.name.toLowerCase().includes(searchLower) || pool.bullToken.symbol.toLowerCase().includes(searchLower) || pool.bearToken.symbol.toLowerCase().includes(searchLower) || pool.chainName.toLowerCase().includes(searchLower) || priceFeedName.toLowerCase().includes(searchLower) ); - }), - [pools, debouncedSearchQuery] - ); + }); + }, [pools, debouncedSearchQuery]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/explorePools/page.tsx` around lines 563 - 576, The filter currently calls debouncedSearchQuery.toLowerCase() for every pool; compute searchLower once outside the callback inside the useMemo to avoid repeated work: inside the useMemo for filteredPools, create a const searchLower = debouncedSearchQuery.toLowerCase() before pools.filter, then use that variable within the filter callback along with existing helpers like getPriceFeedName(pool.priceFeedAddress, pool.chainId); update the dependency array stays [pools, debouncedSearchQuery].
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/hooks/useDebouncedValue.ts`:
- Line 1: This module uses React client hooks (useState, useEffect) in the
useDebouncedValue hook but lacks the Next.js client directive; add the exact
string "use client"; as the first line of the file (before any imports) so the
module is explicitly a client component/module and prevents server-boundary
misuse.
---
Outside diff comments:
In `@src/app/explorePools/page.tsx`:
- Around line 563-576: The filter currently calls
debouncedSearchQuery.toLowerCase() for every pool; compute searchLower once
outside the callback inside the useMemo to avoid repeated work: inside the
useMemo for filteredPools, create a const searchLower =
debouncedSearchQuery.toLowerCase() before pools.filter, then use that variable
within the filter callback along with existing helpers like
getPriceFeedName(pool.priceFeedAddress, pool.chainId); update the dependency
array stays [pools, debouncedSearchQuery].
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4b2ee4a5-d2db-463e-a51a-318415ff8057
📒 Files selected for processing (2)
src/app/explorePools/page.tsxsrc/hooks/useDebouncedValue.ts
|
there is already a useDebouncedSearch hook in src/hooks/useOptimizedData.ts, but I created a new useDebouncedValue hook for this PR instead. Why? Question: |
|
@Atharva0506 Yes, go ahead and remoVe it. |
|
@DengreSarthak removed! |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/hooks/useOptimizedData.ts`:
- Around line 85-92: The issue is that aborted requests still execute their
finally blocks and can set loading=false even while newer requests are pending,
causing the loading state to be incorrectly cleared. To fix this, add a request
ID or version tracking mechanism by creating a unique identifier when
instantiating the AbortController in the request initialization (around lines
85-92), store this identifier in a ref, and then in the finally block (lines
142-145) check that the stored request ID matches the current request ID before
setting loading=false. This ensures only the most recent request can clear the
loading state.
- Around line 149-165: When the key changes and no cached entry exists, the
previous data remains visible until the new fetch completes, causing stale data
from a different key to appear. In the useEffect hook, before calling
fetchData() without arguments (in the uncached fetch path after the cache
check), add a call to setData with an appropriate initial value (such as null or
an empty array depending on the data structure) to clear the previous key's data
immediately, ensuring users don't see stale cross-key data while the new fetch
is in progress.
- Around line 1-5: The useOptimizedData.ts hook module uses React client-side
hooks (useState, useEffect, useCallback, useMemo, useRef) but is missing the
required "use client" directive for Next.js. Add "use client" as the very first
line of the file, before all import statements, to explicitly mark this module
as a client component boundary.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0fcbeb25-46cb-456a-b5d1-e429f5b13b66
📒 Files selected for processing (1)
src/hooks/useOptimizedData.ts
Addressed Issues:
Fixes #86
Screenshots/Recordings:
No visual screenshots applicable. The UI remains visually identical, but performance is optimized. The pool listing now has a 300ms rendering delay while actively typing in the search bar to prevent browser lag.
Additional Notes:
What was fixed and why:
The explorePools/page.tsx component was previously suffering from a performance bottleneck during search operations. The
<PoolSearch />component was passing the keystroke events directly to thesearchQuerystate, and thefilteredPoolsuseMemoblock was depending directly on that raw state.Because the
useMemoblock iterates over the entirepoolsarray and applies 5 different lowercase string matching algorithms (includes) per pool, firing this evaluation synchronously on every single keystroke caused the main thread to block. On devices with lower processing power, or as the number of supported pools grows across multiple chains, this resulted in severe UI freezing and input lag.Implementation Details:
useDebouncedValue<T>: I added a generic, reusable React hook in src/hooks/useDebouncedValue.ts that safely delays state updates by a configured time (default 300ms) usingsetTimeout.searchQuerystate is still updated instantly. This ensures the actual<input>element remains 100% responsive and never drops keystrokes.useMemo: ThefilteredPoolsarray now depends ondebouncedSearchQueryinstead ofsearchQuery. This guarantees that the heavy array filtering operation only fires after the user pauses typing for 300ms, completely resolving the browser lag.We encourage contributors to use AI tools responsibly when creating Pull Requests. While AI can be a valuable aid, it is essential to ensure that your contributions meet the task requirements, build successfully, include relevant tests, and pass all linters. Submissions that do not meet these standards may be closed without warning to maintain the quality and integrity of the project. Please take the time to understand the changes you are proposing and their impact. AI slop is strongly discouraged and may lead to banning and blocking. Do not spam our repos with AI slop.
Check one of the checkboxes below:
I have used the following AI models and tools: TODO
Checklist
Summary by CodeRabbit