Highlight clicked button with React/Tailwind - reactjs

I want to change the appearence of an button after clicking it.
I have tried adding focus: / active:, but react is re-rendering the component on-click, so it doesn't work.
In Javascript I would add an event-handler to every button that would automatically change the appearence after being clicked, how am I able to recreate that in react/tailwind-css, since tailwind is not working with dynamic className changes?
Is there a good practice, or should I add if statements in order to make it work?
This is what I am trying to recreate.
HTML:
<button>MY BUTTON</button>
<button>MY BUTTON</button>
<button>MY BUTTON</button>
JS:
let button_list = document.querySelectorAll("button");
button_list.forEach(element=>{
element.addEventListener("click",function(){
button_list.forEach(remove_background=>{
remove_background.style.background="white";
});
this.style.background="black";
});
});

I would recommend a state variable to store the active button. Here's a simple example:
const ButtonList = () => {
const [activeButtonIndex, setActiveButtonIndex] = useState(0);
return (
<>
<button
className={activeButtonIndex === 0 ? "bg-white" : "bg-black"}
onClick={() => setActiveButtonIndex(0)}
>
My Button
</button>
<button
className={activeButtonIndex === 1 ? "bg-white" : "bg-black"}
onClick={() => setActiveButtonIndex(1)}
>
My Button
</button>
<button
className={activeButtonIndex === 2 ? "bg-white" : "bg-black"}
onClick={() => setActiveButtonIndex(2)}
>
My Button
</button>
</>
);
};

Related

React Mui Autocomplete resets scroll after selecting values

So I'm trying to set up a mui-autocomplete component with additional buttons (Clear all (clear all values and close dropdown) + Apply (set value and close dropdown)) using ListboxComponent.
Issues:
when selecting options from the bottom of the list, the scroll position is reset to the top
cannot close the dropdown programmatically
Here is the ListboxComponent
ListboxComponent={(listBoxProps) => {
return (
<div>
<ul {...listBoxProps} />
<div>
<button
onMouseDown={(event) => {
// Disable blur
event.preventDefault();
}}
onClick={() => {
// clear values
setSelected([]);
}}
>
Clear All
</button>
<button
onMouseDown={(event) => {
// Disable blur
event.preventDefault();
}}
onClick={() => {
// apply value
}}
>
Apply
</button>
</div>
</div>
);
The options are rendered as follows:
renderOption={(optionProps, option, optionState) => {
return (
<li {...optionProps}>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
checked={optionState.selected}
/>
{option}
</li>
);
}}
So I'm using state to keep track of saving the selected values:
const [selectedResult, setSelected] = useState([]);
And when the option is selected - the state is updated
onChange={(event, selectedOptions) => {
setSelected(selectedOptions);
}}
But when the state changes, the component is re-rendered and the scroll is reset. It also seems that I can't use local variables to store the intermediate result, as the state won't update and the checkbox won't update.
StackBlitz link
Is there anything I can do to achieve this?

React. Conditional Button text not working

I have this Button react-bootstrap component
<Button
className="btn-omega has-icon"
onClick={() => { handleFavsClick(data.products)}}
variant=""
>
<Icon size="1.75rem" />
{ liked ? 'Remove from Bookmarks' : 'Add to Bookmarks' }
</Button>
The problem is that text inside conditional if sometimes works and sometimes not
The error message is:
Failed to execute 'insertBefore' on 'Node'
The Icon works fine all the time
const Icon = liked ? BsBookmarkDash : BsFillBookmarkCheckFill
The variable liked is defined here
const key = `like-${id}`
const [liked, setLiked] = useLocalStorage(key, false)
basically is true or false
Is working this way (with a span html tag):
<Button
className="btn-omega has-icon"
onClick={() => { handleFavsClick(data.products)}}
variant=""
>
<Icon size="1.75rem" />
<span>
{ liked ? 'Remove from Bookmarks' : 'Add to Bookmarks' }
</span>
</Button>

Changing material UI button text based on a condition

I am using the material UI button for my component and want to change the button text based on a condition that if order amount is 0, show button text as "cancel" else show "refund". Please help me how can I do the same.
<Button
className={classes.refundButton}
onClick={() => setIsDialogOpen(true)}
>
Refund
</Button>
You can use ternary operator for solution.
<Button
className={classes.refundButton}
onClick={() => setIsDialogOpen(true)}
>
{amount === 0 ? 'Cancel' : 'Refund'}
</Button>
You can just store the state and read from there conditionally...
import { useState } from "react"
const [amount, setAmount] = useState(0)
<Button
className={classes.refundButton}
onClick={() => setIsDialogOpen(true)}
>
{amount === 0 ? 'Cancel' : 'Refund'}
</Button>

ReactJS buttons change color on click

I have 3 buttons in reactjs created with Material UI Buttons.
<>
<Button variant="contained">Button 1</Button>
<Button variant="contained">Button 2</Button>
<Button variant="contained">Button3</Button>
</>
How can I make that when clicking on one, it changes it's color (let's say blue) and the other ones reset to Default?
Because React use JSX, you can put javascript in your html component.
We can imagine a single state that manage your buttons.
in your component you create a state containing integer
const [buttonSelected, setButtonselected] = useState(0);
I'm using the react hook syntax, but it also depend on you implementation.
buttonSelected is the current value of the state and setButtonselected is the function that change the state. When you call it, React will rerender your component and change the display .
You can now add a click function on your return
...
<Button variant="contained" onClick={() => setButtonSelected(1)}>Button 1</Button>
<Button variant="contained" onClick={() => setButtonSelected(2)} >Button 2</Button>
<Button variant="contained" onClick={() => setButtonSelected(3)}>Button3 </Button>
...
This will change the value of buttonSelected each time you click a button.
We now need to change the color , for that we will use use makeStyle, but there is other way to do so.
First, create a style element outside of your component.
const useStyles = makeStyles((theme: Theme) =>
createStyles({
selected: {
background: 'blue',
},
default:{
background: 'default',
}
}
),
);
Then call it in your component
const classes = useStyles();
And finally you can set the style that you want depending on the value
...
<Button className={(buttonSelected === 1) ? classes.selected : classes.default} variant.....
<Button className={(buttonSelected === 2) ? classes.selected : classes.default} variant.....
<Button className={(buttonSelected === 3) ? classes.selected : classes.default} variant.....
...
This is a ternary operator, it's the equivalent of
if(buttonSelected === 1){
return classes.selected
} else {
return classes.default
}
And it should work.
You can learn about it in the conditional rendering of react and in the the styling in react
Dont hesitate if you got any questions :)

antd components are hidden later than the parent div

I have a box which makes itself visible when a button is clicked. The box has a text field and a button. When that button is clicked, the box must hide again. But my problem is the box hides first and for a split second, i still can see the antd components.
box = () => {
<div style={{visibility: this.state.visibility}}>
<Input type= 'text' />
<Button onClick={() => {this.hideBox()}}>Send</Button>
</div>
}
showBox = () => {
this.setState({visibility: 'visible'});
}
hideBox = () => {
this.setState({visibility: 'hidden'});
}
render(){
return(
<div>
<Button onClick={() => {this.showBox()}}>Show</Button>
{this.box()}
</div>
)
}
I don't know how to make them hide at the same time.
Thank you for the help.
style={{display: `${this.state.visibility ? 'block' : 'none'}`}}
because antd components has it's default style: transition:"all 0.3s".
styles in devtool
if you hide it with style, I suggest using dispaly:block/none,instead of visibility.

Resources