Using Leaflet (instead of Folium) in Streamlit to return coordinates on map click

While @randyzwitch has produced a very appreciated Streamlit component for Folium, it’s hard to add any interactivity with the map and send results back into Streamlit.

I feel this is a use case that is more easily addressed by building your own custom Streamlit component over Leaflet. You lose the map building in Python, but you gain full access to the Javascript map interactivity, and I do believe rebuilding all the map elements in Leaflet/JS using data passed from Python is easy enough.

So here is a very quick & dirty implementation of a Streamlit component with Leaflet map where map click returns a value to your Python script : GitHub - andfanilo/streamlit-light-leaflet: Streamlit quick & dirty Leaflet component that sends back coordinates on map click

It also doesn’t use the Streamlit component React template, nor react-leaflet. Yup it’s plain Typescript from the reactless template!

Feel free to take inspiration/fork/reuse/have fun

Fanilo

6 Likes

Another great work, and a nice example on how to use the reactless template! Love it!

Whoa. This is awesome. Are you gonna get it on the gallery?

I actually wanted to build it with Parcel instead of using the reactless webpack template for a lighter build tool chain, but everything kinda broke in the middle :sweat_smile: I’ll try again for another prototype

1 Like

Thanks :blush: hmmm if I also add Python data as Leaflet popups to select, and clean the code and configuration a bit, I will consider it :dizzy:

I disagree that it’s hard, just that no one has added a spec for it yet :laughing:

1 Like

Looks great and is something I was looking for!! So took it as some great inspriration :slight_smile:
Started my own component using the react template, and included the leaflet draw functionality to return the coordinates of drawn layers to python.

https://github.com/maarten-betman/streamlit-leaflet

I’m very new to react and frontend development. When I draw a polyline an set the component value with the polyline coordinates I get two errors:

  1. TypeError: destroy is not a function
  2. TypeError: props.leaflet is undefined.

The coordinates are displayed however below the map.

I think that has something to do with React Hooks and the component lifecycle as it’s reloaded when the component value is returned. I tried using useEffect hook, but without any luck at the moment. Should I save the map state? Any ideas or pointers in what direction I should be looking?

1 Like

Hello @maarten-betman, welcome to the community!

I forked your projet to GitHub - andfanilo/streamlit-leaflet and converted to React hooks everywhere (if you want to check :wink: ), and I’m seeing the same bug as you.

I’m not sure if it comes from you or the react-leaflet-draw plugin though :confused: like you say, it seems the EditControl component tries to access a map inside its own prop that has somewhat been removed after the Streamlit.setComponentValue call (if you comment the setComponentValue everything works…btw if you comment and uncomment it, you see An effect function must not return anything besides a function, which is used for clean-up. You returned: false appear, so maybe we need to move the setComponentValue elsewhere, like in the React Leaflet map events?), but I don’t see in their source code how to preserve the component in a React ref for example to prevent it from unmounting/remounting. I tried fixing a key but it doesn’t help. Also tried implementing the FeatureGroup ref from their example but no luck either.

So yeah I have no concrete advice yet…but I’ll dig in more too on my side, hopefully we’ll find something.

Good luck,
Fanilo

1 Like

Hi @andfanilo! Thanks for your reply!

Thanks for the fork and showing how you would use react hooks, very usefull :slight_smile:. Good point on the react leaflet map events, was already looking at it this morning. I also saw the other error you mentioned. Have a feeling it’s caused when selecting the draw features.

I’ll keep playing around with this in following days to see if I can make some progress!

Will react hooks work inside the react class?

Was reading up on hooks and the docs suggest they only work inside function components?

Yep, React Hooks is only for functional components, which is why I had to convert all your classes into functional components.

It’s a bit of a paradigm change :slight_smile: but you get used to it ahah