rigojr
rigojr

Reputation: 361

Dynamic permanent property for Tooltip leaflet

I'm trying to show a tooltip when a Legend component get hover. For that I have a Father component that has an useState hook in order to pass to the Leaflet Map component the index for an array Location and change the Permanent property if these index are equal.

const permanent = i === showLocationPosition;

The showLocationPosition is the index for the location that is getting hover, getting by props for its Father component.

<Marker
  position={[position[0], position[1]]}
  key={index}
  icon={divIcon({ className: 'marker-dot dot-hover', html: ReactDOMServer.renderToString(stringHTML), iconSize: [30, 30] })}
>
  <Tooltip direction="bottom" opacity={1} offset={new Point(xPoint, 10)} permanent={permanent}>
    <div className={`popup-container-header ${item.count ? 'w-80' : 'w-40 text-center'}`}>
      <p className="w-full">
        {type_of_country_operation ?? item.name}
      </p>
      {item.count && <p>{item.count}</p>}
    </div>
    {item.summary && <p className="popup-container-main">{item.summary}</p>}
  </Tooltip>
</Marker>

I could validate that the permanent variable changes but the Tooltip does not apear.

Any advice ? Thanks!

Upvotes: 2

Views: 2765

Answers (1)

Seth Lutske
Seth Lutske

Reputation: 10714

The reason why the change in permanent doesn't help is because underlying leaflet options are treated as immutable by react-leaflet. So even as your showLocationPosition might change (which changes permanent), the Tooltip was already created and will not respond to changes in that prop.

A quick and dirty way would be to use the key prop on the tooltip also, which can be a combination of the index and the permanent status:

<Tooltip {...otherProps} key={`${index}-${permanent}`}>

This would force a rerender of that Tooltip component when the value of permanent changes.

I would consider a different approach. If you don't need to also render the Tooltip when you mouseover the Marker it originates from, just conditionally render it based on permanent:

<Marker {...markerprops}>
  {permanent && <Tooltip direction="..." offset={...} permanent={permanent}>
    {stuff}
  </Tooltip>}
</Marker>

You may want to change the name permanent to something else, like currentOpenTooltip. Now, if you also want to have the tooltip open and close properly when the user mouses over a marker, you'll need to add a condition for that. You can use a state variable to keep track of what Marker is being moused over, and use event handlers to control that state variable.

const Father = () => {

  const [currentlyMousedOverMarker, setCurrentlyMousedOverMarker] = useState(-1);

  return (
    <MapContainer>
      {markersData.map((marker, index) => {
        <Marker 
          {...markerprops}
          eventHandlers={{
            mouseenter: () => { setCurrentlyMousedOverMarker(index) },
            mouseleave: () => { setCurrentlyMousedOverMarker(-1) }
          }}
        >
          {permanent || currentlyMousedOverMarker === index && 
            (
              <Tooltip permanent={permanent || currentlyMousedOverMarker}>
                {stuff}
              </Tooltip>
            )
          }
        </Marker>
      })}
    </MapContainer>
  )

}

Obviously this code example is simplified and doesn't contain any of the logic you already had for permanent, but its just to give you an idea that the tooltip should only be rendered if either condition is true.

Upvotes: 3

Related Questions