[Bug] Marker crashes with "appendChild" on Activity reappear when Next.js `cacheComponents` is enabled (production-only)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 8.5k
- Forks
- 1.4k
- Avg merge
- 5d 17h
- Merged PRs (30d)
- 3
Description
Description
Related to #2584 but a distinct root cause, not a rapid navigation race condition. This crash occurs on a single normal navigation when
cacheComponents: trueis enabled in Next.js 16, and only in production builds (Webpack). Never reproduces in dev mode (Turbopack).
When Next.js cacheComponents: true is enabled, routes are wrapped in React's <Activity> component. Activity runs useEffect cleanups on hide (navigation away) and re-runs effects on reappear (navigation back).
The Map component's cleanup calls mapbox.destroy() → map.remove(), which sets _container = null and _removed = true on the Mapbox instance. When Activity reappears the route, Marker's useEffect re-fires and calls marker.addTo(map.getMap()). However, map.getMap() returns the destroyed instance with _container = null, resulting in a crash.
Unlike #2584 where _container exists but child elements are partially torn down, here _container is fully null because map.remove() ran to completion during the Activity hide phase.
Expected Behavior
Map and Marker components should reinitialize cleanly when Activity reappears the route. The Mapbox instance should be recreated after it was destroyed during the hide phase.
Steps to Reproduce
- Create a Next.js 16 app with
cacheComponents: trueinnext.config.ts. - Create a page with
<Map>and<Marker>components fromreact-map-gl. - Build for production (
next build && next start) - this does not reproduce in dev mode. - Navigate to the map page → renders fine ✅.
- Navigate away to any other route.
- Navigate back to the map page.
Crash on second visit:
TypeError: Cannot read properties of undefined (reading 'appendChild')
at Marker.addTo
at recursivelyTraverseReappearLayoutEffects
The stack trace recursivelyTraverseReappearLayoutEffects confirms React Activity's reappear phase is the trigger, not a standard remount.
Environment
- Framework version:
react-map-gl@8.1.0(via@vis.gl/react-mapbox) - Map library:
mapbox-gl@3.x - Next.js: 16 (App Router,
cacheComponents: true, production/Webpack only) - React: 19
- Browser: Chrome
- OS: Windows 11
Logs
TypeError: Cannot read properties of undefined (reading 'appendChild')
at Marker.addTo (mapbox-gl)
at eval (marker.ts — useEffect calling marker.addTo(map.getMap()))
at recursivelyTraverseReappearLayoutEffects (react-dom)
at reappearLayoutEffects (react-dom)
Confirmed via instrumentation:
map.getMap()returns the Mapbox instance ✅ (truthy)map.getMap()._removed === true❌ (destroyed during Activity hide)map.getMap()._container === null❌ (set to null bymap.remove())
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in marker.ts, focusing on the useEffect that calls marker.addTo(map.getMap()), then trace the Map cleanup through mapbox.destroy() and map.remove(). Reproduce with a production Next.js 16 build using cacheComponents: true, and verify that navigating away and back recreates the Mapbox instance without the appendChild crash during Activity reappearance.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- next.js, react, typescript
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100