Difficulty: Advanced
Problem
1. DashboardPage.lookup() starts a fetch but never cancels it if the user changes the public key and searches again
frontend/src/pages/DashboardPage.tsx lines 22–38: the lookup function is an inline async that sets loading = true, fires fetch(), and updates state on response. If the user types a new key and clicks Lookup again while the first fetch is still in-flight, two fetches run concurrently. Whichever resolves last wins — the results can be from the first (stale) request.
2. Unlike useQueues which uses a cancelled flag, DashboardPage has no cleanup
frontend/src/hooks/useQueues.ts correctly uses let cancelled = false and checks it before calling setQueues(). The dashboard's inline lookup function has no equivalent guard — it will call setRecords(data) even after the component unmounts or after a second lookup has been initiated.
3. lookup is recreated on every render but never wrapped in useCallback
The function is defined inside the component body without useCallback, creating a new function reference on every render. While this has minimal direct performance impact, it prevents correct memoization if lookup is ever passed to a child component.
Impact: Race conditions between concurrent lookup requests produce flickering, stale results. If the component unmounts while a lookup is in-flight (e.g., user navigates away), React logs a "Can't perform state update on unmounted component" warning and may cause memory leaks.
Proposed Solution
- Add an
AbortController to lookup(): create a new controller on each call, cancel the previous one, pass signal to fetch().
- Track the current controller in a
useRef so it persists across renders.
- Wrap
lookup in useCallback with [publicKey] dependency.
- Add a component unmount cleanup to abort any in-flight request.
Acceptance Criteria
Contributor Note
If assigned, your PR must show a test (in the future frontend test suite) that demonstrates the race condition is resolved, and explain the difference between the cancelled flag pattern used in useQueues and the AbortController approach.
Difficulty: Advanced
Problem
1.
DashboardPage.lookup()starts a fetch but never cancels it if the user changes the public key and searches againfrontend/src/pages/DashboardPage.tsxlines 22–38: thelookupfunction is an inline async that setsloading = true, firesfetch(), and updates state on response. If the user types a new key and clicks Lookup again while the first fetch is still in-flight, two fetches run concurrently. Whichever resolves last wins — the results can be from the first (stale) request.2. Unlike
useQueueswhich uses acancelledflag,DashboardPagehas no cleanupfrontend/src/hooks/useQueues.tscorrectly useslet cancelled = falseand checks it before callingsetQueues(). The dashboard's inlinelookupfunction has no equivalent guard — it will callsetRecords(data)even after the component unmounts or after a second lookup has been initiated.3.
lookupis recreated on every render but never wrapped inuseCallbackThe function is defined inside the component body without
useCallback, creating a new function reference on every render. While this has minimal direct performance impact, it prevents correct memoization iflookupis ever passed to a child component.Impact: Race conditions between concurrent lookup requests produce flickering, stale results. If the component unmounts while a lookup is in-flight (e.g., user navigates away), React logs a "Can't perform state update on unmounted component" warning and may cause memory leaks.
Proposed Solution
AbortControllertolookup(): create a new controller on each call, cancel the previous one, passsignaltofetch().useRefso it persists across renders.lookupinuseCallbackwith[publicKey]dependency.Acceptance Criteria
lookup()usesAbortControllerto cancel previous in-flight requestsfetchreceives{ signal: controller.signal }lookupwrapped inuseCallback([publicKey])Contributor Note
If assigned, your PR must show a test (in the future frontend test suite) that demonstrates the race condition is resolved, and explain the difference between the
cancelledflag pattern used inuseQueuesand theAbortControllerapproach.