Reputation: 2101
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
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
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