Hadi Ranjbar
Hadi Ranjbar

Reputation: 1812

Pass A react component to leaflet popup

I am using leaflet in my react code and I am not using react-leaflet. I want to pass a react component or jsx code to binbPopup function to every tooltip.

let marker = new L.marker(...).bindPopup(<div>Hi</div>)

bindPopup gets string as a input so I cannot use jsx. I also tried to use react portals but still it doesn't work. What is the solution for this problem?

Upvotes: 8

Views: 4620

Answers (2)

C RICH
C RICH

Reputation: 513

Using ReactDOMServer.renderToString() in the client side is not recommended, as it significantly increases the app bundle size, see React docs.

Therefore, the best way to get the HTML string equivalent of a component is:

use createRoot and read HTML from the DOM

import { createRoot } from "react-dom/client";
import { flushSync } from "react-dom";

const popup = (<div>...</div>);

let marker = new L.marker(...).bindPopup(() => {
    const div = document.createElement("div");
    const root = createRoot(div);
    flushSync(() => {
       root.render(popup);
    });
    return div.innerHTML;
});

Upvotes: 3

Murli Prajapati
Murli Prajapati

Reputation: 9733

You can use renderToString method of ReactDOMServer to convert React component to markup string.

import React, { Component } from "react";
import ReactDOM from "react-dom";
import ReactDOMServer from "react-dom/server";
import * as L from "leaflet";
import "./styles.css";

const CustomReactPopup = () => {
  return (
    <div style={{ fontSize: "24px", color: "black" }}>
      <p>A pretty React Popup</p>
    </div>
  );
};

class App extends Component {

  componentDidMount() {
    var map = L.map("map").setView([51.505, -0.09], 13);
    L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
      attribution:
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);

    L.marker([51.5, -0.09])
      .addTo(map)
      .bindPopup(ReactDOMServer.renderToString(<CustomReactPopup />))
      .openPopup();
  }

  render() {
    return (
      <div>
        <div id="map" />
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);  

Working example here: https://codesandbox.io/s/leaflet-with-react-znk11

Upvotes: 13

Related Questions