My Map Disappeared on Refresh: What I Learned About Next.js, SSR, and useEffect

My Map Disappeared on Refresh: What I Learned About Next.js, SSR, and useEffect

While building a real-time dashboard for Waikīkī traffic using TomTom Maps, FastAPI, and Next.js, I ran into a tricky problem that only showed up when I refreshed the page. Everything looked great at first — the map loaded, the layout was responsive, and the live traffic data pulled in from my backend.

Then I hit refresh.


The Problem

The map vanished. Sometimes it briefly flickered and disappeared. Other times the whole layout glitched, rapidly flashing between content and an empty screen. The dev console was no help at first, until I started seeing things like:

  • map container not ready
  • self is not defined
  • Network requests failing, even though they worked before

At one point, it felt like the entire app was stuck in a feedback loop.


The Investigation

My first instinct was to blame the TomTom API key. I regenerated it several times. Then I tried tweaking styles, swapping out layout wrappers, and even rolling back features. None of it solved the issue.

Eventually I realized this had nothing to do with the map or the key — this was a problem with how Next.js was rendering the page.

Next.js uses server-side rendering (SSR) by default, especially in the app directory. That means your React components run in a Node-like environment on the server before reaching the browser. The problem? The TomTom Maps SDK expects the browser window and self globals to exist — and they don't during SSR.

Even wrapping the map code in useEffect wasn't enough, because the parent file wasn't marked as a client component.


What Actually Fixed It

Here's the breakdown of the fixes I implemented:

1. Move the Map to Its Own Component

I created a TomTomMap.tsx file that only handles map logic. This made the component easier to isolate and test.

2. Use a Dynamic Import With SSR Disabled

const TomTomMap = dynamic(() => import("./TomTomMap"), { ssr: false });