foxDev
foxDev

Reputation: 87

map render in the same location before moving to the target location mapbox react hooks

my map load in the same location before moving to the destination choosen by the user. I tried all the ways, I thing something wrong with the onChange, but I coul'd not find the answer.

What I want to achieve is having an input triggered by a button, that search location in the mapbox api and return coordinates, and have the location moved to the target.value

export default function Map() {
  
    const mapContainer = useRef(null);
    const [lng, setLng] = useState(1.43278);
    const [lat, setLat] = useState(38.90889);
    const [zoom, setZoom] = useState(9);
  
    const [searchValue, setSearchValue] = useState("");
  
    useEffect(() => {
      const map = new mapboxgl.Map({
        container: mapContainer.current,
       style: "mapbox://styles/mapbox/streets-v11",
        center: [lng, lat],
        zoom: zoom,
      });
      map.addControl(new mapboxgl.NavigationControl(), "top-right");
      map.on("move", () => {
        setLng(map.getCenter().lng.toFixed(4));
        setLat(map.getCenter().lat.toFixed(4));
        setZoom(map.getZoom().toFixed(2));
      });
    }, []); // eslint-disable-line react-hooks/exhaustive-deps
  
    const handleChange = (event) => {
      event.preventDefault();
      setSearchValue(event.target.value);
    };
    
    const changeMapCenter = () => {
      const map = new mapboxgl.Map({
        container: mapContainer.current,
        style: "mapbox://styles/mapbox/streets-v11",
        center: [lng, lat],
        zoom: zoom,
      });
  
      return fetch(
        `${MAPBOX_PLACES_API}${searchValue}${REST_PLACES_URL}`,
        FETCH_HEADERS
      )
        .then((res) => res.json())
        .then((apiData) => {
          console.log("apidata=>", apiData);
  
          const coordinates = apiData.features[0].center;
  
          console.log("coordinates=>", coordinates);
  
          setLng(coordinates[0]);
          setLat(coordinates[1]);
          new mapboxgl.Marker().setLngLat([lng, lat]).addTo(map);
        });
    };
  
    return (
      <div className="mapBox">
        <div className="sidebar">
          Longitude: {lng} | Latitude: {lat} | Zoom: {zoom}
          <div>
            <label>create your spot collection</label>
            <input
              type="text"
              id="spotLocation"
              onChange={handleChange}
              value={searchValue}
            />
            <button onClick={()=>changeMapCenter()}>search and create </button>
          </div>
        </div>
  
        <div className="map-container" ref={mapContainer} />
      </div>
    );
  }

Upvotes: 0

Views: 603

Answers (1)

Someone Special
Someone Special

Reputation: 13588

You need to fetch your coordinates first, then create the map

const changeMapCenter = async () => {

      const results = await fetch(`${MAPBOX_PLACES_API}${searchValue}${REST_PLACES_URL}`,FETCH_HEADERS).then(res => res.json())

     const coordinates = results.features[0].center
      setLng(coordinates[0]);
      setLat(coordinates[1]);

      const map = new mapboxgl.Map({
        container: mapContainer.current,
        style: "mapbox://styles/mapbox/streets-v11",
        center: [coordinates[0], coordinates[1]], //do not use state lat and lng here and expect it to change, it doesn't.
        zoom: zoom,
      });
  //do not use the state lat and lng here because it's not ready yet since it's async. You need to use coordinates[0]and [1]
    };

reverse coordinates[0] and coordinates[1] if i got them wrong.

Upvotes: 1

Related Questions