Search code examples
reactjsmapbox-gl-jsreact-componentreact-statereact-map-gl

React useState hook not updating state onClick


I am using useState hooks in React and the geojson state will not be updated in the <source data={geojson}> when _updateData is triggered onClick. I think useEffect is overwriting the updated geojson which changes onClick in the _updateData function. What am I missing here in order to update the state of {geojson}? My intent with useEffect is to have the initial goejson onload. Thank you for help. Mapbox library being used: https://uber.github.io/react-map-gl/#/

const Map = () => {
    const [viewport, setViewport] = useState({longitude: -98.58, latitude: 39.83, zoom: 3.5})
    const [geojson, setGeojson] = useState(null)

    useEffect(() => {
        // GeoJSON
        const locations = [];
        let ref = fire.database().ref("...").orderByKey();
        ref.once("value", snapshot => {
            snapshot.forEach(function(childSnapshot) {
                if (childSnapshot.val().Company !== "") {
                    locations.push(childSnapshot.val());
                }
                if (locations.length === 1219) {
                    var geojson = {
                        type: "FeatureCollection",
                        features: locations.map(item => {
                            return {
                                ...
                                },
                                geometry: {
                                type: "Point",
                                coordinates: [item.Long, item.Lat]
                                }
                            };
                        })
                    };
                    setGeojson(geojson);
                    return geojson;
                }
            });
        })
    });

    const _updateViewport = () => {
        setViewport(viewport)
    }

    const _updateData = () => {
        const locations = [];
        let ref = fire.database().ref("...").orderByKey();
        ref.once("value", snapshot => {
            snapshot.forEach(function(childSnapshot) {
                if (childSnapshot.val().Company !== "" && childSnapshot.val().Size === "Large") {
                    locations.push(childSnapshot.val());
                }
                if (locations.length === 232) {
                    var geojson = {
                        type: "FeatureCollection",
                        features: locations.map(item => {
                            return {
                                ...
                                },
                                geometry: {
                                type: "Point",
                                coordinates: [item.Long, item.Lat]
                                }
                            };
                        })
                    };
                    console.log(geojson);
                    setGeojson(geojson);
                    return geojson;
                }
            });
        })
    }

    return (
        <ReactMapGL
            {...viewport}
            onViewportChange={_updateViewport}
            width="100%"
            height="100%"
            mapStyle={mapStyle}
            mapboxApiAccessToken={TOKEN}>
            <Source type="geojson" data={geojson}>
                <Layer {...icon} />
            </Source>
            <div style={navStyle}>
                <NavigationControl onViewportChange={_updateViewport} />
                <button style={navStyle} onClick={_updateData}>Update</button>
            </div>
        </ReactMapGL>
    );
}

export default Map;

Solution

  • use useEffect like this if you want first time load only: useEffect(function,[dependency] or [])