Home > Back-end >  ReferenceError: Window is not defined NextJS13 use Client not working
ReferenceError: Window is not defined NextJS13 use Client not working

Time:01-31

I'm trying to use NextJS 13 with react-leaflet. When I run my component I get window is not defined. I tried using the "use client" at the top of the file and doing a check to see if "typeof window !== undefined" but still no luck. I'm not using the isBrowser function in the snippet before, but that's what I used originally.

pages/censusmap.tsx

'use client';

import { type NextPage } from "next";
import { MapContainer,  TileLayer, GeoJSON } from 'react-leaflet';
// TODO: Fix this import to be from geojson and change the filename
import CensusTractData from "./data/census-tracts_min.json";
import 'leaflet/dist/leaflet.css';
import type {GeoJsonObject, Feature, Geometry} from "geojson";

const isBrowser = () => typeof window !== 'undefined';

const CensusTractMap: NextPage = () => {
  const getCensusTractFillColor = (population2020: number) => {
    if(population2020 <= 2500)
    {
      return "#bd93f9"
    }
    if(population2020 > 2500 && population2020 < 5000) {
      return "#ffb86c"
    }
    if (population2020 > 5000 && population2020 < 10000)
    {
      return "#8be9fd";
    }
    return undefined;
  }
  const censusTractStyle = (val: Feature<Geometry, {pop20: number}> | undefined) => {
    if(!val)
    {
      return {};
    }
    const pop20 = Number(val.properties.pop20);
    return {
                fillColor: getCensusTractFillColor(pop20),
                color: '#44475a',
                weight: 0.5,
                opacity: 1,
                fillOpacity: 0.4,
            }
  }
  return (
    <>
       <div id="map" className="h-180px">
      <MapContainer center={[20.5, -157.510857]} zoom={7} scrollWheelZoom={true}>
        <TileLayer
          attribution='&copy; "Map data © OpenStreetMap contributors, Esri Community Maps contributors, Map layer by Esri'
          url="https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer/tile/{z}/{y}/{x}"
        />
        <GeoJSON data={CensusTractData as GeoJsonObject} style={(val: Feature<Geometry, {pop20: number}> | undefined) => censusTractStyle(val)}/>
      </MapContainer>
    </div>
    </>
  )
}

export default CensusTractMap
error - ReferenceError: window is not defined
    at ...\node_modules\leaflet\dist\leaflet-src.js:230:19
    at ...\node_modules\leaflet\dist\leaflet-src.js:7:66
    at Object.<anonymous> (...\node_modules\leaflet\dist\leaflet-src.js:10:3)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:170:29)
    at ModuleJob.run (node:internal/modules/esm/module_job:198:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:385:24)
    at async importModuleDynamicallyWrapper (node:internal/vm/module:437:15) {
  page: '/censusmap'

CodePudding user response:

I think react-leaflet uses window and when you import it ,it will use window (as you know in ssr window is undefiend)

so add all leaflet related codes to a component and use dynamic import instead

like this :

pages/censusmap.tsx

const CensusmapComponent = dynamic(() => import('../components/CensusmapComponent'), {
  loading: () => 'Loading...',
  ssr: false,
})

return (<CensusmapComponent/>)

GensusmapComponent:

import { MapContainer,  TileLayer, GeoJSON } from 'react-leaflet';
// TODO: Fix this import to be from geojson and change the filename
import CensusTractData from "./data/census-tracts_min.json";
import type {GeoJsonObject, Feature, Geometry} from "geojson";

const isBrowser = () => typeof window !== 'undefined';

const CensusTractMapComponent: React.FC = () => {
  const getCensusTractFillColor = (population2020: number) => {
    if(population2020 <= 2500)
    {
      return "#bd93f9"
    }
    if(population2020 > 2500 && population2020 < 5000) {
      return "#ffb86c"
    }
    if (population2020 > 5000 && population2020 < 10000)
    {
      return "#8be9fd";
    }
    return undefined;
  }
  const censusTractStyle = (val: Feature<Geometry, {pop20: number}> | undefined) => {
    if(!val)
    {
      return {};
    }
    const pop20 = Number(val.properties.pop20);
    return {
      fillColor: getCensusTractFillColor(pop20),
      color: '#44475a',
      weight: 0.5,
      opacity: 1,
      fillOpacity: 0.4,
    }
  }
  return (
      <>
        <div id="map" className="h-180px">
          <MapContainer center={[20.5, -157.510857]} zoom={7} scrollWheelZoom={true}>
            <TileLayer
                attribution='&copy; "Map data © OpenStreetMap contributors, Esri Community Maps contributors, Map layer by Esri'
                url="https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer/tile/{z}/{y}/{x}"
            />
            <GeoJSON data={CensusTractData as GeoJsonObject} style={(val: Feature<Geometry, {pop20: number}> | undefined) => censusTractStyle(val)}/>
          </MapContainer>
        </div>
      </>
  )
}

export default CensusTractMapComponent

and CSS files must be added to _app.js (if it's not module)

in _app.js

 import 'leaflet/dist/leaflet.css';
  • Related