Skip to content

As a developer I want all ESLint warnings resolved so I can have a clean lint output and full hot-reload in dev #253

@ChristopherRotnes

Description

@ChristopherRotnes

Summary

8 pre-existing ESLint warnings remain after PR #252. All are warnings (not errors) so CI passes, but they degrade the dev experience: fast-refresh warnings cause full page reloads instead of hot-swaps when editing those files. None affect runtime correctness.

Priority

Low

Warnings

1. bodymap.jsx — 5× fast-refresh (lines 4, 29, 50, 87, 97)

app/src/lib/bodymap.jsx exports both React components (BodySVG, HeatmapBodySVG) and non-component symbols (MUSCLES, SHAPES, EX_DB, calcMuscles, useIsMobile, color constants). Fast Refresh requires component files to only export components.

Fix: Split into two files:

  • app/src/lib/bodymap.js — all constants and non-component exports (MUSCLES, SHAPES, EX_DB, calcMuscles, useIsMobile, PRIMARY_FILL, etc.)
  • app/src/lib/bodymap.jsx — only BodySVG and HeatmapBodySVG components (imports from the new .js file)

Then update all import sites across the codebase — currently ~15 files import from bodymap.jsx. Use a global search for from.*bodymap to find them all.

2. PageShell.jsx — 1× fast-refresh (line 8)

app/src/components/PageShell.jsx exports the nav shell component plus SectionLabel, PageHeading, PageTitle, AccentChip, StickyCta, BackButton, useNavHints, NavBtn.

Fix: Extract non-component exports to app/src/lib/pageShell.js (or keep in PageShell.jsx but mark the file as non-component with an ESLint disable comment — only acceptable if the split is impractical). useNavHints is a hook and could go to app/src/lib/hooks.js. The styled sub-components (SectionLabel, AccentChip etc.) are imported by most views — update all import sites.

3. theme.jsx — 1× fast-refresh (line 24)

app/src/theme.jsx exports ThemeProvider (component) and useTheme (hook).

Fix: Move useTheme to app/src/lib/hooks.js alongside the existing useDebouncedSearch and useFetch hooks. Update all import sites (useTheme is used in several components).

4. App.jsx — 1× setState-in-effect (line 52)

useEffect(() => {
  if (session && !localStorage.getItem("wl-intro-seen")) setIntroOpen(true);
}, [session]);

setIntroOpen(true) is called synchronously inside the effect body. The lint rule react-hooks/set-state-in-effect flags this as a potential source of cascading renders.

Fix: Derive the initial value from useState initialiser instead of an effect:

const [introOpen, setIntroOpen] = useState(
  () => !!session && !localStorage.getItem("wl-intro-seen")
);

Or, if session is not available at mount time (it comes from Supabase auth and may arrive asynchronously), keep the effect but verify whether a layout effect or a ref guard is more appropriate. Check App.jsx around line 45–55 for context before choosing an approach.

Files to touch

  • app/src/lib/bodymap.jsx → split
  • app/src/lib/bodymap.js → new file (constants/utils)
  • app/src/components/PageShell.jsx → extract non-component exports
  • app/src/theme.jsx → remove useTheme
  • app/src/lib/hooks.js → add useTheme
  • app/src/App.jsx → fix setState-in-effect
  • All files importing from bodymap.jsx, PageShell.jsx, or theme.jsx → update import paths

Acceptance criteria

  • npm run lint outputs 0 problems (0 errors, 0 warnings)
  • npm test still passes (91 tests)
  • App loads and hot-reloads correctly in dev (swa start)
  • No runtime regressions — body map, theme toggle, nav shell all work

Out of scope

  • Any logic changes to the components themselves
  • Adding new tests (existing suite covers the affected modules)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions