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='© "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='© "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';