Im using Next.js 14.1.0 version and im using leaflet map in my project in two custom hook and i got this error in my development running console.
⨯ node_modules\leaflet\dist\leaflet-src.js (230:18) @ window ⨯ ReferenceError: window is not defined at webpack_require (H:\Web_Design\Next.js\Kashan_Yab.next\server\webpack-runtime.js:33:43) at eval (./hooks/use-custom-map.tsx:12:65) at (ssr)/./hooks/use-custom-map.tsx (H:\Web_Design\Next.js\Kashan_Yab.next\server\app(main-layout)(footer-layout)\ads\page.js:1125:1) at webpack_require (H:\Web_Design\Next.js\Kashan_Yab.next\server\webpack-runtime.js:33:43) at eval (./hooks/use-leaflet-map.tsx:11:73) at (ssr)/./hooks/use-leaflet-map.tsx (H:\Web_Design\Next.js\Kashan_Yab.next\server\app(main-layout)(footer-layout)\ads\page.js:1191:1) at webpack_require (H:\Web_Design\Next.js\Kashan_Yab.next\server\webpack-runtime.js:33:43) at eval (./hooks/index.ts:20:74) at (ssr)/./hooks/index.ts (H:\Web_Design\Next.js\Kashan_Yab.next\server\app(main-layout)(footer-layout)\ads\page.js:1103:1) at webpack_require (H:\Web_Design\Next.js\Kashan_Yab.next\server\webpack-runtime.js:33:43) at eval (./services/businesses/filter/GetBusinesses.ts:6:64) at (ssr)/./services/businesses/filter/GetBusinesses.ts (H:\Web_Design\Next.js\Kashan_Yab.next\server\app(main-layout)(footer-layout)\ads\page.js:1466:1) at webpack_require (H:\Web_Design\Next.js\Kashan_Yab.next\server\webpack-runtime.js:33:43) at eval (./services/businesses/index.ts:26:80) at (ssr)/./services/businesses/index.ts (H:\Web_Design\Next.js\Kashan_Yab.next\server\app(main-layout)(footer-layout)\ads\page.js:1521:1) at webpack_require (H:\Web_Design\Next.js\Kashan_Yab.next\server\webpack-runtime.js:33:43) at eval (./store/archive-store.ts:9:78) at (ssr)/./store/archive-store.ts (H:\Web_Design\Next.js\Kashan_Yab.next\server\app(main-layout)(footer-layout)\ads\page.js:1686:1) at webpack_require (H:\Web_Design\Next.js\Kashan_Yab.next\server\webpack-runtime.js:33:43) at eval (./store/index.ts:9:72) at (ssr)/./store/index.ts (H:\Web_Design\Next.js\Kashan_Yab.next\server\app(main-layout)(footer-layout)\ads\page.js:1708:1) at webpack_require (H:\Web_Design\Next.js\Kashan_Yab.next\server\webpack-runtime.js:33:43) at eval (./components/providers/AppProvider.tsx:10:64) at (ssr)/./components/providers/AppProvider.tsx (H:\Web_Design\Next.js\Kashan_Yab.next\server\app(main-layout)(footer-layout)\ads\page.js:553:1) at webpack_require (H:\Web_Design\Next.js\Kashan_Yab.next\server\webpack-runtime.js:33:43) null
use-custom-map.tsx
"use client";
import { Icon } from "leaflet";
import { MutableRefObject, useRef, useState } from "react";
import {
MapContainer,
MapContainerProps,
Marker,
TileLayer,
useMap,
useMapEvents,
} from "react-leaflet";
import { Each } from "@/components/utils/Each";
import "leaflet/dist/leaflet.css";
const ClickHandler = ({
onClick,
}: {
onClick: (lat: number, lng: number) => void;
}) => {
useMapEvents({
click: (e) => {
const { lat, lng } = e.latlng;
onClick(lat, lng);
},
});
return null;
};
const GetMap = ({ map }: { map: MutableRefObject<any> }) => {
map.current = useMap();
return null;
};
export const mapMarker = new Icon({
iconUrl: "/images/map/marker-icon.png",
shadowUrl: "/images/map/marker-shadow.png",
iconSize: [25, 32],
iconAnchor: [18, 40],
shadowAnchor: [17, 50],
});
export const homeMarker = new Icon({
iconUrl: "/images/map/home.webp",
shadowUrl: "/images/map/marker-shadow.png",
iconSize: [50, 50],
iconAnchor: [23, 50],
shadowAnchor: [10, 40],
});
export const branchMarker = new Icon({
iconUrl: "/images/map/shop.webp",
shadowUrl: "/images/map/marker-shadow.png",
iconSize: [50, 50],
iconAnchor: [23, 50],
shadowAnchor: [10, 40],
});
export const flagMarker = new Icon({
iconUrl: "/images/map/flag.webp",
iconSize: [50, 50],
iconAnchor: [37, 49],
});
export const locationMarker = new Icon({
iconUrl: "/images/map/location.webp",
shadowUrl: "/images/map/marker-shadow.png",
iconSize: [50, 50],
iconAnchor: [24, 49],
shadowAnchor: [10, 40],
});
const defaultLocation: LocationInfo = {
lat: 33.969292153047476,
lng: 51.40714968697455,
};
const useCustomMap = ({
mapProps,
isClickable,
clickableMarkerInfo,
markerInfos,
customMarker,
markerType,
}: {
mapProps?: MapContainerProps;
isClickable?: boolean;
clickableMarkerInfo?: LocationInfo;
markerInfos?: LocationInfo[];
customMarker?: React.ReactNode;
markerType?: MarkerType;
}) => {
const map = useRef();
const mainMarker = markerType
? markerType === "Home"
? homeMarker
: markerType === "Branch"
? branchMarker
: markerType === "Flag"
? flagMarker
: locationMarker
: mapMarker;
const [info, setInfo] = useState<LocationInfo>(
clickableMarkerInfo ? clickableMarkerInfo : defaultLocation
);
const markersOutput = Each<LocationInfo>({
of: markerInfos!,
render: (marker) => (
<Marker
position={[marker.lat, marker.lng]}
icon={mainMarker}
></Marker>
),
});
const mapClickHandler = (lat: number, lng: number) => {
setInfo({
lat,
lng,
});
};
if (map.current) (map.current as any).getCenter();
const output = (
<MapContainer
{...(isClickable && clickableMarkerInfo
? { center: [clickableMarkerInfo.lat, clickableMarkerInfo.lng] }
: markerInfos && markerInfos.length
? { center: [markerInfos[0].lat, markerInfos[0].lng] }
: { center: [defaultLocation.lat, defaultLocation.lng] })}
zoom={13}
{...mapProps}
>
<TileLayer
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<GetMap map={map} />
{isClickable ? <ClickHandler onClick={mapClickHandler} /> : <></>}
{!isClickable ? (
customMarker ? (
customMarker
) : markersOutput !== -1 ? (
markersOutput
) : (
<></>
)
) : (
<Marker
position={[info.lat, info.lng]}
icon={mainMarker}
></Marker>
)}
</MapContainer>
);
return { output, map, info };
};
export default useCustomMap;
use-leaflet-map.tsx
"use client";
import { useEffect } from "react";
import { Form, FormInstance, Input } from "antd";
import useCustomMap from "./use-custom-map";
import "leaflet/dist/leaflet.css";
const useLeafletMap = (
form: FormInstance<any>,
defaultInfo?: LocationInfo,
className?: string,
isInModal: boolean = false,
markerType?: MarkerType,
) => {
const {
output: mapOutput,
info,
map,
} = useCustomMap({
mapProps: {
className: `custom-map ${className ? className : ""}`,
},
isClickable: true,
clickableMarkerInfo: defaultInfo
? {
lat: defaultInfo.lat!,
lng: defaultInfo.lng!,
}
: undefined,
markerType
});
useEffect(() => {
if ( typeof window !== "undefined" ) {
if (isInModal) {
if (map.current) {
(map.current as any).invalidateSize();
} else {
setTimeout(() => {
if (map.current) (map.current as any).invalidateSize();
}, 500);
}
}
form.setFieldsValue({
lat: info.lat,
lng: info.lng,
});
}
}, [defaultInfo, map.current, isInModal, form, info]);
const output = (
<>
<Form.Item name="lat">
<Input type="hidden" />
</Form.Item>
<Form.Item name="lng">
<Input type="hidden" />
</Form.Item>
{mapOutput}
</>
);
return output;
};
export default useLeafletMap;
give me a right solution of fixing this error in Next.js