diff --git a/src/app/[lang]/crag/[cragSlug]/info/page.tsx b/src/app/[lang]/crag/[cragSlug]/info/page.tsx
index e39b33c..5e8f87c 100644
--- a/src/app/[lang]/crag/[cragSlug]/info/page.tsx
+++ b/src/app/[lang]/crag/[cragSlug]/info/page.tsx
@@ -28,9 +28,9 @@ import Map from "@/components/map/map";
import Button from "@/components/ui/button";
import IconMissing from "@/components/ui/icons/missing";
import Link from "@/components/ui/link";
-import { TMarker } from "@/components/map/lazy-map";
import { IconSize } from "@/components/ui/icons/icon-size";
import IconMore from "@/components/ui/icons/more";
+import { TMarker } from "@/components/map/map-marker";
type TCragInfoPageParams = {
cragSlug: string;
diff --git a/src/components/map/lazy-map.tsx b/src/components/map/lazy-map.tsx
index 0825207..1498802 100644
--- a/src/components/map/lazy-map.tsx
+++ b/src/components/map/lazy-map.tsx
@@ -1,18 +1,11 @@
"use client";
-import { MapContainer, Marker, Popup, TileLayer } from "react-leaflet";
+import { MapContainer, TileLayer } from "react-leaflet";
import L, { FitBoundsOptions } from "leaflet";
import "leaflet/dist/leaflet.css";
-import ReactDOMServer from "react-dom/server";
-import IconMarker from "../ui/icons/marker";
import { ReactNode } from "react";
import "./map.css";
-
-type TMarker = {
- type: "parking" | "wall";
- position: [number, number];
- popupContent?: ReactNode;
-};
+import MapMarker, { TMarker } from "./map-marker";
type TLazyMapProps = {
children?: ReactNode;
@@ -64,21 +57,7 @@ function LazyMap({
/>
{markers?.map((marker, index) => (
-
- ),
- iconSize: [52, 52],
- iconAnchor: [26, 52],
- popupAnchor: [0, -46],
- })}
- position={marker.position}
- >
- {marker.popupContent}
-
+
))}
{children}
@@ -86,5 +65,5 @@ function LazyMap({
);
}
-export type { TLazyMapProps, TMarker };
+export type { TLazyMapProps };
export default LazyMap;
diff --git a/src/components/map/map-marker.tsx b/src/components/map/map-marker.tsx
new file mode 100644
index 0000000..8cca2d6
--- /dev/null
+++ b/src/components/map/map-marker.tsx
@@ -0,0 +1,39 @@
+import { Marker, Popup } from "react-leaflet";
+import L from "leaflet";
+import IconMarker from "../ui/icons/marker";
+import { ReactNode } from "react";
+import { useClientRenderToString } from "@/hooks/useClientRenderToString";
+
+type TMapMarkerProps = {
+ marker: TMarker;
+ index: number;
+};
+
+type TMarker = {
+ type: "parking" | "wall";
+ position: [number, number];
+ popupContent?: ReactNode;
+};
+
+function MapMarker({ marker, index }: TMapMarkerProps) {
+ const [icon] = useClientRenderToString();
+
+ return (
+
+ {marker.popupContent}
+
+ );
+}
+
+export type { TMarker };
+export default MapMarker;
diff --git a/src/components/map/map.css b/src/components/map/map.css
index 909a9d7..b347b47 100644
--- a/src/components/map/map.css
+++ b/src/components/map/map.css
@@ -1,6 +1,6 @@
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
- @apply bg-white shadow-lg;
+ @apply bg-white shadow-lg;
}
.leaflet-popup-content-wrapper {
diff --git a/src/hooks/useClientRenderToString.tsx b/src/hooks/useClientRenderToString.tsx
new file mode 100644
index 0000000..7dabb73
--- /dev/null
+++ b/src/hooks/useClientRenderToString.tsx
@@ -0,0 +1,41 @@
+import { useEffect, useState } from "react";
+import { createRoot } from "react-dom/client";
+
+type TUseClientRenderToString = (
+ input: React.ReactElement | React.ReactElement[],
+ deps?: any[]
+) => string[];
+
+const clientRenderToString = (element: React.ReactElement): Promise =>
+ new Promise((resolve) => {
+ const container = document.createElement("div");
+ const renderCallback = () => {
+ resolve(container.firstElementChild?.innerHTML || "");
+ };
+
+ createRoot(container).render({element}
);
+ });
+
+export const useClientRenderToString: TUseClientRenderToString = (
+ input,
+ deps = []
+) => {
+ const [htmlStringList, setHtmlStringList] = useState([]);
+ const elementList = Array.isArray(input) ? input : [input];
+
+ useEffect(() => {
+ (async () => {
+ const markupPromises = elementList.map(clientRenderToString);
+ const markup: string[] = await Promise.all(markupPromises);
+
+ if (!setHtmlStringList) {
+ return;
+ }
+
+ setHtmlStringList(markup);
+ })();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, deps);
+
+ return htmlStringList;
+};