Search code examples
javascriptreactjsleafletreact-leafletremix.run

How to add react-leaflet map to remixjs app


I'm trying to add a react-leaflet map to a remix app. I created a simple app using the npx create-remix@latest command. I then added react-leaflet using the installation instructions. Now I have the following code:

index.tsx

import type { MetaFunction } from "@remix-run/node";
import { ClientOnly } from "remix-utils/client-only";
import LazyMap from "~/components/LazyMap";

export const meta: MetaFunction = () => {
  return [
    { title: "New Remix App" },
    { name: "description", content: "Welcome to Remix!" },
  ];
};

export default function Index() {
  return (
      <div>
        test 123
        <ClientOnly fallback={<p>Loading...</p>}>
          {() => <LazyMap />}
        </ClientOnly>
      </div>
  );
}

LazyMap.tsx

import { Suspense, lazy } from 'react';
const Map = lazy(() => import('./Map'));

export default function LazyMap() {
    return (
        <Suspense fallback={<div>Loading...</div>}>
            <Map />
        </Suspense>
    );
}

Map.tsx

import { MapContainer } from 'react-leaflet/MapContainer'
// import { Marker } from 'react-leaflet/Marker'
// import { Popup } from 'react-leaflet/Popup'
// import { TileLayer } from 'react-leaflet/TileLayer'
import { ClientOnly } from 'remix-utils/client-only';


export default function Map() {
    return (
        <div>
            test 123
            <ClientOnly>
              {() => (
                <MapContainer zoom={13} scrollWheelZoom={false}>
                  test
                </MapContainer>
              )}
            </ClientOnly>
        </div>
    );
}

Even though I've wrapped the Map in a lazy import from LazyMap it appears to still be trying to process the Map file, which of course references leaflet and causes the dreaded ReferenceError: window is not defined error. How can I overcome this error?


Solution

  • The ClientOnly utility is great when rendering the component causes a reference to some client-side-only global variable like window or document, but it can only wrap component code you've imported, and imports can have side-effects...like referencing window or document.

    According to the official remix docs you can add a .client.ts/tsx/js/jsx suffix to your file to have it excluded from the SSR.