S1: usePlot bypasses exhaustive-deps — fragile closure contract #6

Open
opened 2026-06-05 10:22:07 +00:00 by sebse · 0 comments
Owner

Code Smell

File: web/components/ChartCard/usePlot.ts:71

The entire build() deps array is handed off to parent via the deps: DependencyList parameter. The rebuild callback wraps deps with an eslint-disable-next-line react-x/exhaustive-deps comment. If parent omits a dependency, stale closure bugs can occur (wrong rows, old colorMap).

Code reference

// eslint-disable-next-line react-x/exhaustive-deps
}, deps);

Why it matters

Bypassing exhaustive-deps removes all compile-time safety. Parent must manually keep deps in sync.

Suggestion

Document the contract explicitly in the JSDoc, or restructure usePlot to use refs for stable closures and trigger rebuild via a separate mechanism.

## Code Smell **File:** `web/components/ChartCard/usePlot.ts:71` The entire `build()` deps array is handed off to parent via the `deps: DependencyList` parameter. The `rebuild` callback wraps `deps` with an `eslint-disable-next-line react-x/exhaustive-deps` comment. If parent omits a dependency, stale closure bugs can occur (wrong `rows`, old `colorMap`). ### Code reference ```ts // eslint-disable-next-line react-x/exhaustive-deps }, deps); ``` ### Why it matters Bypassing exhaustive-deps removes all compile-time safety. Parent must manually keep deps in sync. ### Suggestion Document the contract explicitly in the JSDoc, or restructure `usePlot` to use refs for stable closures and trigger rebuild via a separate mechanism.
sebse added the code-smell label 2026-06-05 10:22:07 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sebse/factorio-signal-exporter#6