NewToJS
NewToJS

Reputation: 2101

Add/Remove CSS classes for buttons in a React Component

In my ReactJS component below I'm rendering 3 buttons using React.createElement(). I want to add functionality where the button clicked on gets a 'selected' class and all the other buttons get an 'unselected' class. Furthermore, when the component firsts loads I'd like the first button ('Select All') to have the 'selected' class.

Right now I've written this button logic using jQuery but I'm wondering how I could do this in all React.

class Mychart extends React.Component {

    constructor(props) {
      super(props);
      this.state = {}
    }

    handleClick(i) {
      // for all buttons: remove 'selected' class, add 'unselected' class 
      $('.custom-btn').removeClass('selected').addClass('unselected');
      // for the button we're clicking on: remove the 'unselected' class, add 'selected' class
      $('.custom-btn[index='+i+']').removeClass('unselected').addClass('selected');
    }

    render() {
     [{label: 'Select All', label: 'Select Legacy', label: 'Select Kids'}].map((button, i) => {
       return React.createElement('button', {className: i === 0 ? 'custom-btn selected' : 'custom-btn unselected', index: i, onClick: () => {this.handleClick(i)} }, button.label)
     });
    }
}

ReactDOM.render(React.createElement(Mychart), parent);

Upvotes: 0

Views: 715

Answers (2)

ControlAltDel
ControlAltDel

Reputation: 35011

Using CSS, you can create a style for the focused button, like:

button.custom-btn:focus {
    color: green;
}

or

button:focus {
    color: green;
}

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074495

The standard React way to do this is to remember which button is the "selected" one with state (although as ControlAltDel points out, in this specific case you probably want to use CSS instead):

class Mychart extends React.Component {

    constructor(props) {
      super(props);
      this.state = {
          // *** Start with none selected
          selected: -1,
      };
    }

    handleClick(i) {
        this.setState({selected: i});
    }

    render() {
        // Get the selected one
        const {selected} = this.state;
        return [{label: 'Select All'}, {label: 'Select Legacy'}, {label: 'Select Kids'}].map((button, i) => {
            return React.createElement(
                'button',
                {
                    // *** Use the selected index
                    className: i === selected ? 'custom-btn selected' : 'custom-btn unselected',
                    key: i, // *** `key`, not `index`
                    onClick: () => {
                        this.handleClick(i);
                    }
                },
                button.label
            );
        });
    }
}

ReactDOM.render(React.createElement(Mychart), document.getElementById("root"));
.custom-btn.selected {
    color: green;
}
<div id="root"</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

(Felt very odd doing this without JSX. :-D )

Note: I had to fix a couple of errors in your code, the primary one being that you had an array with just one object with a repeated label property in it, rather than an array of objects.

In your code you were working by index so that's how I did the example above, but I would probably give each element a unique ID instead (or use label, if label is unique):

class Mychart extends React.Component {

    constructor(props) {
      super(props);
      this.state = {
          // *** Start with none selected
          selected: "",
      };
    }

    handleClick(label) {
        this.setState({selected: label});
    }

    render() {
        // Get the selected one
        const {selected} = this.state;
        return [{label: "Select All"}, {label: "Select Legacy"}, {label: "Select Kids"}].map(({label}, i) => {
            return React.createElement(
                "button",
                {
                    // *** Use the selected index
                    className: label === selected ? "custom-btn selected" : "custom-btn unselected",
                    key: label, // *** `key`, not `index`
                    onClick: () => {
                        this.handleClick(label);
                    }
                },
                label
            );
        });
    }
}

ReactDOM.render(React.createElement(Mychart), document.getElementById("root"));
.custom-btn.selected {
    color: green;
}
<div id="root"</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

Upvotes: 4

Related Questions