1

I have a react functional component that takes a button as a variable, and launches a function on click. The button is a variable because this function is getting imported into another functional component, and the button is created in this external function. I would also like to set and toggle the button class on click, to indicate whether the button/tool is active or not. I have not been able to find a way to toggle the className. In my example I am using the useState hook to set a default value for the class, and then in the click function I am changing the value of the class depending on the value of another useState hook. This does not show any class for the button. I can specify the className as activeClass outside of the click function and it will that class, but can't figure out how to toggle. I have also tried setting the className in the return statement like this: <button className={btnActive ? 'one_class' : 'two_class'} onClick={function}</> but this also does not set the class. What am I doing wrong? This is my first attempt at using the react framework.

import React from 'react';
import { useInput } from '../hooks/useInput';
import {
    placesSource,
    places_lyr,
}
    from "../qgis2web/layers";
import {
    increaseThrobberCounter,
    decreaseThrobberCounter
}
    from "../qgis2web/throbberCounter";
import { addLayer, getErrorMessage, removeLayer } from "../qgis2web/qgis2web";
import { add_geojson_feats } from "../qgis2web/addGeojsonFeatures";

declare const ol, $, toastr;


const GetPlacesControl = ({ map, launchButton }) => {

    const [btnActive, setBtnState] = React.useState<boolean>(false);
    const [activeClass, setClass] = React.useState("fas fa-globe-americas");

    function clear_places_features(map) {
        placesSource.clear();
        removeLayer(places_lyr);
    }

    const toggle_get_places = (launchButton) => {
        setBtnState((btnActive) => {
            setClass((activeClass) => {
            if (btnActive) {
                setClass("fas fa-ban");
                $('html,body').css('cursor', 'default');
                map.un('click', runCallback);
                clear_places_features(map);

            } else {
                setClass("fas fa-globe-americas");
                $('html,body').css('cursor', 'crosshair');
                map.on('click', runCallback);
            }
            launchButton.className = activeClass;
            return launchButton.className;
        });
            return !btnActive;

        });
    }
    const runCallback = React.useCallback((evt) => {

        clear_places_features(map);

        $.ajax({
            type: "POST",
            contentType: "application/json;charset=utf-8",
            url: "api/get_places?x=" + evt.coordinate[0] + "&y=" + evt.coordinate[1],
            traditional: "true",
            datatype: "json",
            mimeType: 'application/json',
        }).done(function (response) {
            const places_feats = new ol.format.GeoJSON().readFeatures(response);

            if (places_feats.length == 0) {
                toastr.warning('no records found, try again');
            } else {
                placesSource.addFeatures(places_feats);
                map.getView().fit(placesSource.getExtent());
                places_lyr.setVisible(true);
                addLayer(places_lyr);
            }
        }).fail(function (jqXHR) {
            let msg = getErrorMessage(jqXHR);
            toastr.error(msg);
        }).always(function () {
            decreaseThrobberCounter();
        });
    }, []);

    React.useEffect(() => {
        const get_coords_on_click = (evt) => {
            let loc_coords = evt.coordinate;
            return loc_coords;
        };

        launchButton.addEventListener('click', toggle_get_places, false);
        map.on('singleclick', get_coords_on_click);

        return () => {
            launchButton.removeEventListener('click', toggle_get_places);
            map.un('singleclick', get_coords_on_click);
        };
    }, []);


    return (
        <button onClick={launchButton.toggle_get_places}></button>
    );
};

export default GetPlacesControl;
2
  • I think you should be able to <button className={activeClass} ....> Commented Oct 13, 2021 at 17:28
  • @zac I did try that, also does not work Commented Oct 13, 2021 at 18:14

1 Answer 1

2

Your code does not work

You should try to use useRef and classList.add/remove

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for the reply, can you point me to example of how this should be implemented?
You can pass id to your button, document.getElementById("buttonID").classList.toggle("YourClassName")
thank you, I was able to add a class, but could not remove and add then another.
Use classList.toggle
but its not that i want to change visibility, i want to change the style/icon on the button.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.