ReactJs adding active class to button - javascript

I have five buttons, dynamically created. My target is: when any button is clicked to add active class to it, and of course if any other has that active class to remove it. How can I achieve that?
<div>
{buttons.map(function (name, index) {
return <input type="button" value={name} onClick={someFunct} key={ name }/>;
})}
</div>

You need to introduce state to your component and set it in onClick event handler. For example output of render method:
<div>
{buttons.map(function (name, index) {
return <input
type="button"
className={this.state.active === name ? 'active' : ''}
value={name}
onClick={() => this.someFunct(name)}
key={ name } />;
})}
</div>
event handler (element method):
someFunct(name) {
this.setState({ active: name })
}

One of the easiest way to add active class is setting state and changing that state on each switch, by the state value you can change the active class of the item.
I also had an same issue with switching the active class in list.
Example:
var Tags = React.createClass({
getInitialState: function(){
return {
selected:''
}
},
setFilter: function(filter) {
this.setState({selected : filter})
this.props.onChangeFilter(filter);
},
isActive:function(value){
return 'btn '+((value===this.state.selected) ?'active':'default');
},
render: function() {
return <div className="tags">
<button className={this.isActive('')} onClick={this.setFilter.bind(this, '')}>All</button>
<button className={this.isActive('male')} onClick={this.setFilter.bind(this, 'male')}>male</button>
<button className={this.isActive('female')} onClick={this.setFilter.bind(this, 'female')}>female</button>
<button className={this.isActive('child')} onClick={this.setFilter.bind(this, 'child')}>child</button>
<button className={this.isActive('blonde')} onClick={this.setFilter.bind(this, 'blonde')}>blonde</button>
</div>
}
});
hope this will help you!

One of the easiest solution for adding active class to the current button (highlight it) for react developers.
const {useState,Fragment} = React;
const App = () => {
const [active, setActive] = useState("");
const handleClick = (event) => {
setActive(event.target.id);
}
return (
<Fragment>
<button
key={1}
className={active === "1" ? "active" : undefined}
id={"1"}
onClick={handleClick}
>
Solution
</button>
<button
key={2}
className={active === "2" ? "active" : undefined}
id={"2"}
onClick={handleClick}
>
By
</button>
<button
key={3}
className={active === "3" ? "active" : undefined}
id={"3"}
onClick={handleClick}
>
Jamal
</button>
</Fragment>
);
}
ReactDOM.render(
<App/>,
document.getElementById("react")
);
.active{
background-color:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Related

onClick function is not called after I have enabled the button in Reactjs

I have a textarea and a button. The button is disabled by default and when the user starts typing, I enable the button to be clicked. But the problem is that, the onClick function is not called while already disabled = false was set.
I've seen this: button onClick doesn't work when disabled=True is initialized (Reactjs)
Seems to be a good idea, but after I setState with the new value, my component is re-rendering, and I don't really want that.
const refText = useRef(null);
const refBtn = useRef(null);
function handleBtnStatus(e) {
let text = e.target.value;
if(text.replace(/\s/g, "").length > 0) {
refBtn.current.disabled = false;
}
else {
refBtn.current.disabled = true;
}
}
function postThis() {
console.log("You posted! Text:", refText.current.value);
// disable again
refBtn.current.disabled = true;
// delete previous text wrote
refText.current.value = "";
}
return (
<>
{isLogged && (
<div className="container">
<div className="content">
<div className="utool-item-text">
<textarea name="textArea" placeholder="Write something.." ref={refText} onChange={(e) => handleBtnStatus(e)}></textarea>
</div>
<div className="utool-item-post">
<button className="ust-btn-post" ref={refBtn} disabled={true} onClick={postThis}>Da Tweet</button>
</div>
</div>
<div className="posts-section">
<div className="list-posts">
{posts.map((p) => {
return (p.hidden === false ? (
<div className="post" key={p.id}>
<div className="post-text">
<span>{p.text}</span>
</div>
</div>
) : (''))
})}
</div>
</div>
</div>
)}
</>
)
Any help?
Use state instead of refs, re-rendering is ok for your case
Simplified example:
import React, { useState } from 'react';
const SimpleExample = () => {
const [textAreaValue, setTextAreaValue] = useState('');
return (
<>
<button disabled={!textAreaValue} onClick={() => console.log('onClick handler')}>
click me
</button>
<textarea value={textAreaValue} onChange={(e) => setTextAreaValue(e.target.value)} />
</>
);
};
And I would recommend checking this Use state or refs in React.js form components?

How to toggle the css of a mapped button?

I'm just trying to figure out how to toggle a css class for an individual button that is generated from a mapped array.
My code works, but it toggles every mapped button, not just the button selected.
<div className='synonym-keeper'>
{synArr.map((syn) => (
<button
className={`synonym ${isPressed && 'active'}`}
onClick={() => toggleIsPressed(!isPressed)}
>
{syn}
</button>
))}
</div>
How do I make just the selected button's css toggle?
Create another component called Togglebutton and keep the toggle logic in it. That way you can toggle the individual button.
This would also work:
const synArr = ["button 1", "button 2", "button 3"];
const ToggleButton = ({ text }) => {
const [isPressed, toggleIsPressed] = React.useState(false);
return (
<button
className={`synonym ${isPressed && "active"}`}
onClick={() => toggleIsPressed(!isPressed)}
>
{text}
</button>
);
};
function App() {
return (
<div className="synonym-keeper">
{synArr.map((syn) => (
<ToggleButton text={syn} key={syn}/>
))}
</div>
);
}
ReactDOM.render(<App />, document.querySelector('.react'));
.synonym.active {
background-color: green;
}
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div class='react'></div>
I resolved it by making an array for the className and changing its contents onClick, as below:
<div className='synonym-keeper'>
{synArr.map((syn, idx) => (
<button
className={`synonym ${isPressed[idx]}`}
onClick={() => {
const newIsPressed = [...isPressed];
newIsPressed[idx] === ''
? (newIsPressed[idx] = 'active')
: (newIsPressed[idx] = '');
setIsPressed(newIsPressed);
}}
>
{syn}
</button>
))}
</div>
This resolves the issue and allows me to select one or more buttons sequentially. I really like the cleanliness of Amila's answer though so I will mark theirs as accepted.

How to handle mapped elements individually by a button of each created while mapping array?

I have created a carousel which is a column of ten dates ,for this i am mapping dates by momentjs, Inside each of this column , i am mapping different time slots for morning ,afternoon and evening,
and i have a functionality that only shows first two time slots and then there is a show more button, by clicking on this button more time slots are appear,but whenver i am clicking on this button all of the columns time slots is appearing, i have to handle all the column button individually..
Thank You in adavance... :)
below is my code...
const [showMoreClicked, setShowMoreClicked] = useState(false);
const [showMoreAfternoon, setShowMoreAfternoon] = useState(false);
const [showMoreEvening, setShowMoreEvening] = useState(false);
const showMoreSlotsForMorning = (e) => {
e.preventDefault();
setMoreClicked(!showMoreClicked);
};
const showMoreSlotsForAfternoon = (e) => {
e.preventDefault();
setShowMoreAfternoon(!showMoreAfternoon);
};
const showMoreSlotsForEvening = (e) => {
e.preventDefault();
setShowMoreEvening(!showMoreEvening);
};
<Carousel responsive={responsive}>
{nexttendates.map((elem, dateIndex) => {
return (
<div>
<button key={dateIndex} className="nexttendates">
{elem}
</button>
<div className="appointment-timelots">
<div className="availableslots">
<div className="availableslot">
<img
src="../elements/doctorlist/doctorcard/sunrise.png"
alt=""
className="sunrise"
/>
Morning
</div>
</div>
</div>
{morningtime.map((elem, morInd, arr) => {
if (showMoreClicked == false) {
while (morInd == 0 || morInd == 1)
return (
<button key={morInd} className="appointtimes">
{elem}
</button>
);
} else {
return (
<button key={morInd} className="appointtimes">
{elem}
</button>
);
}
})}
<button
choseIndex={dateIndex}
onClick={showMoreSlotsForMorning}
className="appointtimes"
>
{showMoreClicked ? "Show Less" : "Show More"}
</button>
<img
src="../elements/doctorlist/doctorcard/sun.png"
alt=""
className="afternoon"
/>
Afternoon
{afternoontime.map((elem, aftInd) => {
if (showMoreAfternoon == false) {
while (aftInd == 0 || aftInd == 1)
return (
<button className="appointtimes">{elem}</button>
);
} else {
return (
<button className="appointtimes">{elem}</button>
);
}
})}
<button
choseIndex={dateIndex}
onClick={showMoreSlotsForAfternoon}
className="appointtimes"
>
{showMoreAfternoon ? "Show Less" : "Show More"}
</button>
<img
src="../elements/doctorlist/doctorcard/night-mode.png"
alt=""
className="evening"
/>
Evening
{eveningtime.map((elem, eveInd) => {
if (showMoreEvening == false) {
while (eveInd == 0 || eveInd == 1) {
return (
<button className="appointtimes">{elem}</button>
);
}
} else {
return (
<button className="appointtimes">{elem}</button>
);
}
})}
<button
choseIndex={dateIndex}
onClick={showMoreSlotsForEvening}
className="appointtimes"
>
{showMoreEvening ? "Show Less" : "Show More"}
</button>
</div>
);
})}
</Carousel>
i think its happening because of i have mapped an array and only used one useState to check open or not...Can anybody plz help me....
Make the time slots list as a separate component, so that each of the morning, afternoon, and evening list will have their own state automatically for toggling display.
Something like this example:
import { useState } from "react";
// Toggle showMore value on click
const SlotsList = ({ slots }) => {
const [showMore, setShowMore] = useState(false);
const handleShowMoreClick = () => {
setShowMore((prev) => !prev);
};
// Filter the slots prop before map it if showMore is false
return (
<div>
{slots
.filter((elem, index) => (showMore ? true : index <= 1))
.map((elem, index) => (
<button key={index} className="appointtimes">
{elem}
</button>
))}
<button onClick={handleShowMoreClick} className="appointtimes">
{showMore ? "Show Less" : "Show More"}
</button>
</div>
);
};
export default SlotsList;
In this example, the list is filtered before being mapped out for an easier solution. The key property should be replaced by a unique ID to avoid conflict.
It can then be imported and used like below in the main component. Also reusable for all 3 lists, and each have separate display toggle.
<SlotsList slots={morningtime} />

Add active class by default to the first element from class list and change active class on click next js

I'm a newbie in react. I have two class in css file. One is btn and another is active. I want to set an active class to the first button by default and when I click on other buttons it'll be remove and add to the current button. I'll be thankful if anyone help me about this. Thanks in advance.
Here is my codes
import React, {useState} from 'react';
const Tab = () => {
const [tabBtn, setTabBtn] = useState(false);
const handleBtn = () => {
setTabBtn(true);
}
return (
<div className='btnContainer'>
<button className={"btn" + (tabBtn ? " active" : "")} onClick={handleBtn}>One</button>
<button className='btn'>Two</button>
<button className='btn'>Three</button>
<button className='btn'>Four</button>
<button className='btn'>Five</button>
<button className='btn'>Six</button>
<button className='btn'>Seven</button>
</div>
);
}
export default Tab;
Use this code :
className={`btn ${tabBtn ? " active" : ""}`}
So let's make a few optimizations here:
First let's put an array of all your buttons and then use state to track which one is selected.
import React, {useState} from 'react';
const buttonList = ['One', 'Two', 'Three', 'Four'];
const Tab = () => {
const [tabBtn, setTabBtn] = useState('One');
return (
<div className='btnContainer'>
{
buttonList.map(b => {return (
<button
className={b === tabBtn ? 'active' : '' }
key={`${b}Button`}
onClick={() => setTabBtn(b)}
>
{b}
</button>)}
)}
</div>
);
}
export default Tab;
Without map
import React, {useState} from 'react';
const Tab = () => {
const [tabBtn, setTabBtn] = useState('One');
return (
<div className='btnContainer'>
<button
className={'One' === tabBtn ? 'active' : '' }
key={`One Button`}
onClick={() => setTabBtn('One')}
>
One
</button>
<button
className={'Two' === tabBtn ? 'active' : '' }
key={`Two Button`}
onClick={() => setTabBtn('Two')}
>
Two
</button>
</div>
);
}
export default Tab;
Obviously, add in the rest of the buttons up to 7.

How to Create 2D Grid by Repeating a Component certain times in a Loop in reactJS?

I am Working on Movie Ticket Booking Website. I Want to make a Grid Layout of 4x7. So What i Thought is i would Create a button Component and repeat it in Loop Several Times.
Pseudo Code:
for(var i=0;i<4;i++){
for(var j=0;j<7;j++){
button Component();
}
newline Component();
}
But this type of thing is not supported in reactjs. So What Can i Do for Implementation of above thing? Also When a button is clicked i want to change its color for that i have given ID to button Component so i can do it by DOM Manipulation but how to do that using UseState?
EDIT: I am done with array part but what about Color Change now? I Tried DOM but it returns NULL
CODE:
const items=[];
for(let i=1;i<=20;i++){
let style={
backgroundColor:"White"
};
items.push(<button className="btn btn-danger" onClick={()=>changeColor(i)} style={style} id={"button"+i}/>);
}
function changeColor(index) {
document.getElementById("index").style.backgroundColor="Green";
}
This Thing returns NULL i Do not know why
Using direct DOM manipulation is not recommended, you should instead leverage the reactive render cycle that React provides.
Here is a snippet which declares a Button component that handles its own internal state as an example. Mutiple Buttons are rendered inside a map() in the parent, and each button then controls its own active state.
const { useState } = React;
function App() {
return (
<div>
{[1,2,3].map(n =>(
<Button key={n} label={'Button' + n} />
))}
</div>
)
}
function Button({label}) {
const [active, setActive] = useState(false);
const handleClick = (e) => {
setActive(a => !a);
};
return (
<button
type='button'
className={active ? 'active' : ''}
onClick={handleClick}
>
{label}
</button>
)
}
ReactDOM.render(<App />, document.getElementById('root'));
.active {
background-color: tomato;
}
<script src="https://unpkg.com/react#17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom#17/umd/react-dom.production.min.js"></script>
<div id='root'></div>
But generally buttons will be used to interact directly with the parent's state, in which case the click handler and state logic will be declared in the parent, with relevant properties being passed down to the children.
const { useState } = React;
function App() {
const [buttons, setButtons] = useState([
{id: 1, label: 'Button 1', active: false},
{id: 2, label: 'Button 2', active: false},
{id: 3, label: 'Button 3', active: false}]);
const handleClick = (buttonId) => {
setButtons(buttons => buttons.map(b =>
b.id === buttonId
? {...b, active: !b.active}
: b));
};
return (
<div>
{buttons.map(b =>(
<Button key={b.id} id={b.id} label={b.label} onClick={handleClick} active={b.active} />
))}
</div>
)
}
function Button({label, id, onClick, active}) {
return (
<button
type='button'
onClick={() => onClick(id)}
className={active ? 'active' : ''}
>
{label}
</button>
)
}
ReactDOM.render(<App />, document.getElementById('root'));
.active {
background-color: tomato;
}
<script src="https://unpkg.com/react#17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom#17/umd/react-dom.production.min.js"></script>
<div id='root'></div>

Categories

Resources