Skip to content

[Bug] Marker crashes with "appendChild" on Activity reappear when Next.js cacheComponents is enabled (production-only) #2588

@AbdulSamad94

Description

@AbdulSamad94

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: true is 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

  1. Create a Next.js 16 app with cacheComponents: true in next.config.ts.
  2. Create a page with <Map> and <Marker> components from react-map-gl.
  3. Build for production (next build && next start) - this does not reproduce in dev mode.
  4. Navigate to the map page → renders fine ✅.
  5. Navigate away to any other route.
  6. 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 by map.remove())

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions