1

I'm trying to display the country name on hover using simple-map react with react tooltip. With the console log on mouse enter I realised that on hover I actually get the name of the country and the rest of the info I need. Then i try to set it on the setTooltipContent and display it on hover, but it doesnt work

My map.js component

import React, { useState, useEffect, memo} from "react";
import { ComposableMap, Geographies, Geography, Annotation, ZoomableGroup, Sphere, Graticule, Marker} from "react-simple-maps";

import {scaleLinear} from "d3-scale";

const geoUrl =
  "https://raw.githubusercontent.com/zcreativelabs/react-simple-maps/master/topojson-maps/world-110m.json";

//darker color for more population
  const colorScale = scaleLinear().domain([0, 6500000]).range(["yellow", "red"])


  const Map = ({ setTooltipContent }) => {
    const [countries, setCountries] = useState([])
    const [continents, setContinents] = useState([])
    const [ position, setPosition ] = useState({coordinates:[0, 0], zoom: 1})

    const handleMoveEnd = (position) => {
        setPosition(position)
    }

    const rounded = num => {
        if (num > 1000000000) {
          return Math.round(num / 100000000) / 10 + "Bn";
        } else if (num > 1000000) {
          return Math.round(num / 100000) / 10 + "M";
        } else {
          return Math.round(num / 100) / 10 + "K";
        }
      };

    const getData = () => {
        fetch('http://localhost:3001/countries', {
            header: {
                'Content-Type': 'application/json',
                'Accept': 'application/json',
            }
        })

        .then((res) => res.json())
        .then((data) =>{setCountries(data)})
    }

    const getContData = () => {
        fetch('http://localhost:3001/continent', {
            header: {
                'Content-Type': 'application/json',
                'Accept': 'application/json',
            }
        })

        .then((res) => res.json())
        .then((data) =>{setContinents(data)})
    }

    useEffect(() => {
        getData();
        getContData();
    }, [])
    
return(
    <div className="map">
      
        <div style={{width: '50vw', height: '50vh'}}>
            <ComposableMap
            width={900}
            height={400}
            projectionConfig={{
                rotate: [-10, 0, 0],
                scale:147
            }}>
                {
                    countries.length >0 
                    ?
                    <ZoomableGroup
                        zoom={position.zoom}
                        center={position.coordinates}
                        onMoveEnd={handleMoveEnd}>
                            <Sphere stroke="#000" strokeWidth={0.3}/> 
                             <Graticule stroke="#000" strokeWidth={0.3}/>
                            
                            <Geographies geography={geoUrl}>
                                {
                                    ({geographies}) => 
                                    geographies.map((geo, index )=> {
                                        const isos = countries.find((s) => s.ISO3 === geo.properties.ISO_A3)
                                        
                                        return (
                                            <>
                                            <Geography
                                                key={index}
                                                geography={geo}
                                                fill= {isos ?  colorScale(isos["population_density"]) : 'red'} 
                                                onMouseEnter={() => {
                                                    
                                                    const { NAME, POP_EST } = geo.properties;
                                                    console.log(`${NAME} — ${rounded(POP_EST)}`)
                                                    setTooltipContent(`${NAME} — ${rounded(POP_EST)}`);
                                                  }}
                                                  onMouseLeave={() => {
                                                    setTooltipContent("");
                                                  }}
                                                  style={{
                                                    
                                                    hover: {
                                                      fill: "cyan",
                                                      outline: "none"
                                                    },
                                                    pressed: {
                                                      fill: "cyan",
                                                      outline: "none"
                                                    },
                                                    default: {
                                                        outline: 'none'
                                                    }
                                                    
                                                  }}
                                                  />
                                   
                                       </>
                                                )
                                    })
                                }
                            </Geographies>
                        
                        </ZoomableGroup>
                    :
                    <p>Loading</p>
                }
                </ComposableMap>

        </div>


    </div>
);
}

export default  memo(Map);

my app.js

import './App.css';
import React, {useState} from 'react';
import Map from './components/Map';
import ReactTooltip from "react-tooltip";

function App() {
  const [content, setContent] = useState("");

  return (
    <div className="App">
     <Map setTooltipContent={setContent}/>
     <ReactTooltip>{content}</ReactTooltip>
    </div>
  );
}

export default App;

1 Answers1

0

It may be a little late but I had the same problem, and I wasted my time poking around the wrong documentation, the documentation of react-simple-maps. The answer to our problem lies in the documentation of React-Tooltip.
The problem is that the tooltip does show up, but it shows up somewhere out of sight. In my case, I had a component fixed to a small size and overflow set to hidden, so it showed up hidden :)
Fortunately, the react-tooltip library allows us to pass offset props to it. It works similar to the CSS position property (according to my understanding).
Here's my implementation, where you call the ReactTooltip component:

import React, {useState} from 'react';
import Map from './components/Map';
import ReactTooltip from "react-tooltip";

function App() 
{
  const [content, setContent] = useState("");

  return (
    <div className="App">
     <Map setTooltipContent={setContent}/>

     //you can adjust the top and left according to your needs
     <ReactTooltip offset={{ top: 335, left: 45 }} >
        {content}
     </ReactTooltip>

    </div>
  );
}

export default App;

Here's the link to the react-tooltip documentation:
https://www.npmjs.com/package/react-tooltip

Hope that was helpful!

Uzair_07
  • 141
  • 1
  • 9