Problem
src/components/ContractEventFeed.tsx defines load as a plain async function inside the component body. The polling useEffect (lines 77–83) references load but its dependency array is [live, pollInterval] — load is omitted. This creates a stale closure: the interval callback permanently holds a reference to the load instance captured at the time the effect ran, which closes over the contractId value at that moment.
When the parent re-renders ContractEventFeed with a new contractId prop, the initial fetch useEffect fires correctly for the new ID (line 71), but the polling interval continues calling the old load closure — which still fetches the previous contractId. Events for the new contract never appear until the interval is manually cleared or the component unmounts.
A second related problem: the initial useEffect(() => { load(); }, [contractId]) also omits load from its dependency array, which ESLint react-hooks/exhaustive-deps would flag.
Solution
Memoize load with useCallback and include contractId and limit as its dependencies. Add load to both useEffect dependency arrays:
const load = useCallback(async () => {
if (!contractId.trim()) return;
// ... existing fetch logic
}, [contractId, limit]);
Acceptance Criteria
Note for Contributors: If you're assigned to this issue, write a clear and detailed description for your pull request. Explain what was changed, why it was needed, how it was implemented, and include any relevant testing or screenshots where applicable.
Problem
src/components/ContractEventFeed.tsxdefinesloadas a plain async function inside the component body. The pollinguseEffect(lines 77–83) referencesloadbut its dependency array is[live, pollInterval]—loadis omitted. This creates a stale closure: the interval callback permanently holds a reference to theloadinstance captured at the time the effect ran, which closes over thecontractIdvalue at that moment.When the parent re-renders
ContractEventFeedwith a newcontractIdprop, the initial fetchuseEffectfires correctly for the new ID (line 71), but the polling interval continues calling the oldloadclosure — which still fetches the previouscontractId. Events for the new contract never appear until the interval is manually cleared or the component unmounts.A second related problem: the initial
useEffect(() => { load(); }, [contractId])also omitsloadfrom its dependency array, which ESLintreact-hooks/exhaustive-depswould flag.Solution
Memoize
loadwithuseCallbackand includecontractIdandlimitas its dependencies. Addloadto bothuseEffectdependency arrays:Acceptance Criteria
loadis wrapped inuseCallbackwith[contractId, limit]dependenciesuseEffecthooks includeloadin their dependency arrayscontractIdprop immediately restarts polling for the new contractreact-hooks/exhaustive-depsESLint warnings onContractEventFeedliveis toggled