kflaw
kflaw

Reputation: 424

How do I toggle className for button variable in react functional component?

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;

Upvotes: 1

Views: 282

Answers (1)

Ali Yaghoubi
Ali Yaghoubi

Reputation: 1280

Your code does not work

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

Upvotes: 2

Related Questions