user11566024
user11566024

Reputation:

unable to update state using react useState

I am learning react hooks. In my code I have set the initial values for plotting map as

//map state
const [mapData, setMapData] = useState(
    { lat: 40.712776, lng: -74.0059, zoom: 5 }
);

In the useEffect() call back I am loading the map once

useEffect(() => {
    initMap();
}, []); // run once

Inside the initMap() there is map.on() method to get the updated geo locations. The initMap() is

const initMap = () => {
    mapboxgl.accessToken = 'token';
    const map = new mapboxgl.Map({
        container: mapContainer,
        style: 'mapbox://styles/mapbox/streets-v11',
        center: [mapData.lng, mapData.lat],
        zoom: mapData.zoom
    }); // load the map with init values

    // update the `mapData` as map move
    map.on('moveend', () => {
        const { lng, lat } = map.getCenter(); // logs the updated lat and lon
        setMapData({ lat: lat.toFixed(4), lng: lng.toFixed(4), zoom: map.getZoom().toFixed(2) }); // suppose to set the updated value
        console.log(mapData); // not logging updated values!
    });
}

The setMapData() is not setting the state. But the map.on is called and is logging the values.

Upvotes: 0

Views: 1186

Answers (2)

Dae
Dae

Reputation: 21

This is also the case for useSelector. I don't believe React Hooks is being supported by Mapbox in this way. I have event handlers I add onto my map and those handlers cannot access the current values of the component's useState/useSelector. These values are always the values they were when the event handlers were added to the map. I have resorted to adding another state that triggers useEffects instead of handling it all in my event handler.

edit: It was brought to my attention that you can use redux's 'useStore' hook to grab the current redux store even in the Mapbox event handlers! It's tougher to test, however, bc you have to mock the 'useStore' manually. Hope that helps!

Upvotes: 2

Avin Kavish
Avin Kavish

Reputation: 8947

setState is asynchronous, updated state may or may not be available to statements following it.

Use an effect hook that runs on a mapData update to react to changes.

useEffect(() => console.log(mapData), [mapData])

Upvotes: 1

Related Questions