Skip to content

[bug] places-map: setState called synchronously in useEffect causes cascading re-render on every map load #42

Description

@yakew7

What happened?

What happened?

places-map.tsx hydrates URL state by calling setFilters and setFocusId
directly inside a useEffect body on mount:

This triggers a second render immediately after the first — the component
mounts with empty state, then re-renders with the URL values.
ESLint (react-hooks/set-state-in-effect) flags both setState calls.

React.useEffect(() => {
  const state = parseMapState(window.location.search);
  setFilters({ types: state.types, cities: state.cities });
  setFocusId(state.placeId);
  hydrated.current = true;
}, []);

What did you expect to happen?

State should be derived from the URL on the first render, not patched in
after it.

Error reported on lines 47–48:
Calling setState synchronously within an effect can trigger cascading renders

Proposed fix
Use lazy useState initialisers so the URL is parsed once at mount, with no
effect needed:

const [filters, setFilters] = React.useState<PlaceFilters>(() => {
  if (typeof window === "undefined") return { types: [], cities: [] };
  const state = parseMapState(window.location.search);
  return { types: state.types, cities: state.cities };
});
const [focusId, setFocusId] = React.useState<string | null>(() => {
  if (typeof window === "undefined") return null;
  return parseMapState(window.location.search).placeId ?? null;
});

Steps to reproduce

Run ESLint on src/components/map/places-map.tsx:
node_modules/.bin/eslint src/components/map/places-map.tsx

Browser and OS

No response

Screenshots or console logs (optional)

No response

Checklist

  • I searched existing issues and this is not a duplicate.
  • This is not a security vulnerability (those go to anay@studymap.dev).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No fields configured for Bug.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions