Change the tileLayer using the React useEffect hook

1k Views Asked by At

I'm trying to change the tileLayer using React's useEffect hook. This stops when switching from DarkMode to LightMode Theme thus changing the tileLayer to a Dark and vice versa.

I've read hundreds of pages and tried many alternatives but it just doesn't work at all. Can someone help me please?

React Leaf v3.2.0

import React, { useState, useEffect, useContext } from "react";
import { Grid } from "@material-ui/core";
import { DarkContext } from '../../../Context/DarkContext';

import { MapContainer, Marker, Popup, TileLayer } from "react-leaflet";
import "leaflet/dist/leaflet.css";

import icon from "../constants";

const zoom = 13;

function Map({ regionCoord, regionName }) {
  const [map, setMap] = useState(null);
  const { isDarkModeCont } = useContext(DarkContext);

  const L = require("leaflet");

  const mapa1 = L.tileLayer("https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png")
  const mapa2 = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png")
  
      
  function turnLightMap() {
    mapa1.removeFrom(map);
      mapa2.addTo(map);
  }

  function turnDarkMap() {
    mapa2.removeFrom(map);
      mapa1.addTo(map);
  }

  // useEffect(() => {   
  //   if(isDarkModeCont == true) {
  //     turnDarkMap()
  //   } else {
  //     turnLightMap()
  //   }
  // }, [isDarkModeCont])

  return (
    <>
      <Grid container>
        <Grid item xs={10}>
          {regionCoord && (
            <MapContainer
              center={[50, 50]}
              zoom={zoom}
              style={{ height: "90vh" }}
              whenCreated={setMap}
            >
              <TileLayer
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                url={"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"}
              />

              <Marker position={regionCoord} icon={icon}>
                <Popup>{regionName}</Popup>
              </Marker>
            </MapContainer>
          )}
        </Grid>
        <Grid item xs={2}>          
          <button onClick={() => turnLightMap()}>Light Map</button>
          <button onClick={() => turnDarkMap()}>Dark Map</button>
        </Grid>
      </Grid>
    </>
  );
}

export default Map;

Clicking on the buttons changes the map but if I activate useEffect it is showing this error:

Error

1

There are 1 best solutions below

0
On

The problem was because useEffect was asynchronous. I resolved it by including just a confirmation that the map was created through useState that is generated in "whenCreated = {setMap}" including useEffect:

useEffect(() => {   
    if(isDarkModeCont == true && map) {
      turnDarkMap()
    } 
    if(isDarkModeCont == false && map) {
      turnLightMap()
    }
  }, [isDarkModeCont]) 

I don't know if there is another way but this ended up solving my problem. If someone knows otherwise and wants to leave it below for everyone to see it would be interesting. Thank you all.