Add a class for the active button ReactJS - reactjs

When you click on a button, you should change its class. When I click on one of the buttons, the class changes for both. I need the class to be added only to the active button, and if I click on another, then the first button will have the class disappear and the second will appear. Where is the error?
import React, { Component } from 'react';
class trueName extends Component {
constructor(props) {
this.state = {
name: {},
};
}
editName = (names)=>{
this.setState({name:names});
}
someFunct(name) {
this.setState({ active: name })
}
render() {
const {name}=this.state;
return(
<div >
<div className="SelectName">
<span>{this.state.name}</span>
</div>
<button
className={this.state.active === name ? 'active' : ''}
onClick={ () => {this.editName(John);this.someFunct(name)}}
key ='1'>
<span>My name John</span>
</button>
<button
className={this.state.active === name ? 'active' : ''}
onClick={ () => {this.editName(Donald);this.someFunct(name)}}
key ='2'
>
<span>My name Donald</span>
</button>
</div>
)
}
}
export default trueName;

You are setting state.name and then setting state.active to the same value, so this.state.active === this.state.name is always true and the active class gets applied.
This might help:
constructor(props) {
super(props)
this.state = {
name: null
}
}
editName = name => {
this.setState({ name: name })
}
render() {
const { name } = this.state
return (
<div>
<div className="SelectName">
<span>
<pre>{name}</pre>
</span>
</div>
<button
className={name === "John" ? "active" : ""}
onClick={() => {
this.editName("John")
}}
>
<span>My name John</span>
</button>
<button
className={name === "Donald" ? "active" : ""}
onClick={() => {
this.editName("Donald")
}}
>
<span>My name Donald</span>
</button>
</div>
)
}

Related

Add class to following buttons inside a map function

I have a function that adds class onClick.
import * as React from 'react'
class ThisClass extends React.Component<any,any> {
constructor(){
super()
this.state = {active: ''}
this.ThisFunction = this.ThisFunction.bind(this)
}
const items = ['button1', 'button2', 'button3']
ThisFunction (i) {
this.setState({
active: i
})
}
render(){
return(
<div>
{
items.map((item, i) => {
return(
<button
onClick={()=>this.ThisFunction(i)}>{item}
className={`this_button ${this.state.active ? 'active' : ''}`}
{item}
</button>
)
})
}
</div>
)
}
}
export default ThisClass
What's suppose to happen:
<div>
<button class='this_button active'>button1</button>
<button class='this_button active'>button2</button>
<button class='this_button'>button3</button>
</div>
What's really happening:
<div>
<button class='this_button active'>button1</button>
<button class='this_button'>button2</button>
<button class='this_button'>button3</button>
</div>
I need to have a maximum of two active' class onClick function. Is there any way to get around this?
Change your state to hold an array of active indices and change the handler to only maintain the last two set (i.e. kick out the least recently used)
state = {
active: []
};
thisFunction = i => {
if (this.state.active.includes(i)) return; // already active!!
const active = [...this.state.active, i].slice(-2); // keep last 2
this.setState({ active });
};
You also had some syntax errors in the button rendering. The classname was being set as part of the button text. Set the active class if this.state.active array includes the active index
{["button1", "button2", "button3"].map((item, i) => {
return (
<button
onClick={() => this.thisFunction(i)}
className={`this_button ${
this.state.active.includes(i) ? "active" : ""
}`}
>
{item}
</button>
);
})}
There are some major errors in your code.
You are putting the className property as a child on the button, is an attribute instead
Every child on a list e.g your buttons needs to have a key
You are binding twice the function, one on the constructor and another one on the onClick event using an arrow function. Bind a function
class ThisClass extends React.Component {
constructor(){
super()
this.state = {active: ''}
}
ThisFunction (i) {
this.setState({
active: i
})
}
render(){
const items = ['button1', 'button2', 'button3']
return(
<div>
{
items.map((item, i) => {
return(
<button
key={i}
onClick={() => this.ThisFunction(i)}
className={`this_button ${this.state.active === i ? 'active' : ''}`}>
{item}
</button>
)
})
}
</div>
)
}
}
ReactDOM.render(
<ThisClass />,
document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

How to toggle class on onclick in map function?

Toggling on a single element is a breeze. But I'm having a difficulty toggling with map function. Clicking a child element should toggle "active". But what's happening is that every element gets the class "active". Take a look:
constructor() {
super()
active: false
this.toggleClick = this.toggleClick.bind(this)
}
toggleClick() {
this.setState(state=> ({
active: !state.active
})
)
}
...in my function class...
function ThisClass(props){
return(
<div>
{
items.map((item,i) => {
return(
<span role="button" className={`${props.active ? 'active' : ''}`} key={i} onClick={() => props.toggleClick(i)}>{item.text}</span>
)
})
}
</div>
)
}
This is my desired output:
<div>
<span class="active">A</span>
<span class="">B</span>
<span class="">C</span>
</div>
Instead, this becomes the result
<div>
<span class="active">A</span>
<span class="active">B</span>
<span class="active">C</span>
</div>
And of course, toggling should be working. a single click would make the current active. And clicking it again would remove the active state. Also, By clicking the current state, the previous active element should be stripped off with active.
Here's my own solution(along with #404notBrighton): In my state:
...instead of
this.state = {active:false}
I've changed it to
this.state = {active:null}
in my toggleClick() I've put
this.setState({ active: i });
if (this.state.active === i) {
this.setState({ active: null })
}
then finally in my class...
<span role="button" className={`${props.active === i ? 'active' : ''}`} key={i} onClick={() => props.toggleClick(i)}>
try assigning your "active" state an index instead of a boolean
change your code
from
className={${props.active ? 'active' : ''}}
to
className={${props.active === i ? 'active' : ''}}
Your toggle function must look like this
toggleClick(i) {
this.setState({ active: i })
}
As I understand, you want to have only one active item.
You need to keep two state like selectedItemId and selectedItemState.
And update their values when button is clicked.
So you can try something like this:
import React, { Component } from "react";
class App extends Component {
state = {
items: [{ id: 1, text: "A" }, { id: 2, text: "B" }, { id: 3, text: "C" }],
selectedItemId: null,
selectedItemState: false
};
toggleClick = id => {
if (id === this.state.selectedItemId) {
this.setState({
selectedItemState: !this.state.selectedItemState
});
} else {
this.setState({
selectedItemId: id,
selectedItemState: true
});
}
};
render() {
const { selectedItemId, selectedItemState } = this.state;
return this.state.items.map(el => (
<div key={el.id}>
<span
role="button"
className={
el.id === selectedItemId && selectedItemState ? "active" : ""
}
onClick={() => this.toggleClick(el.id)}
>
{el.text} -{" "}
{el.id === selectedItemId && selectedItemState ? "active" : "passive"}
</span>
<br />
</div>
));
}
}
export default App;
Sample codesandbox:
https://codesandbox.io/s/spring-thunder-w711z

React Toggle Active Class between multiple Reactstrap Buttons

I am new to React and Reactstrap. I am trying to set the active class or active attribute to a single button onclick. My current setup toggles all the buttons at the same time. What the best way to toggle the active states independently between the buttons states when clicked?
import React, { Component } from 'react'
import { Button } from "reactstrap";
export class Payment extends Component {
constructor(props) {
super(props);
this.state = {
paymentSelection: 'credit',
active: false
}
}
toggleContent = (event) => {
const currentState = this.state.active;
event.preventDefault();
this.setState({
paymentSelection: event.target.value,
active: !currentState
})
}
switchContent = (value) => {
switch (value) {
case 'credit':
return <div>
<p>Credit Content Here</p>
</div>;
case 'paypal':
return <div>
<p>PayPal Content Here</p>
</div>;
case 'amazon':
return <div>
<p>Amazon Content Here</p>
</div>;
case 'more':
return <div>
<p>More Content Here</p>
</div>;
default:
return null;
}
}
render() {
const { paymentSelection } = this.state;
const { active } = this.state;
return (
<div className="container-fluid payment-btn-group">
<Button outline className={active ? 'active': null} color="secondary" value="credit" onClick={this.toggleContent} >Credit Card</Button>
<Button outline className={active ? 'active': null} color="secondary" value="paypal" onClick={this.toggleContent} >PayPal</Button>
<Button outline className={active ? 'active': null} color="secondary" value="amazon" onClick={this.toggleContent} >Amazon</Button>
<Button outline className={active ? 'active': null} color="secondary" value="more" onClick={this.toggleContent} >+ More</Button>
{this.switchContent(paymentSelection)}
</div>
);
}
}
export default Payment
You can set active class like this
className={paymentSelection ==='credit' ? 'active' : null}
You already have payment selection in the state you just need to check that apply it.
Demo

How to implement a React container which can handle all events from its sub-components?

Assume that the container contains 3 buttons:
<Container>
<Button1/> <Button2> <Button3/>
</Container>
By default, all buttons are in 'Normal' state. If I click on Button1, I'd like to have Button1 becomes 'Active' state (with solid background) and Button2 & Button3 become 'Inactive' state (with gray border).
What's the best way to achieve that in React?
Name is a valid html attribute to use in buttons. If you want to use React to control this, you can simply have a state property attributed to the selected button's name. With that state, you can control the disabled attribute, as well as the class name.
this.state = {
activeButton: null
};
onButtonClick = (e) => {
const { name } = e.target;
this.setState({
activeButton: name
});
};
render() {
const { activeButton } = this.state;
return (
<Component>
<button
className={`${activeButton === 'one' && 'active' || ''}`}
onClick={this.onButtonclick}
name="one"
disabled={activeButton !== 'one'}>
Button 1
</button>
<button
className={`${activeButton === 'two' && 'active' || ''}`}
onClick={this.onButtonclick}
name="two"
disabled={activeButton !== 'two'}>
Button 2
</button>
<button
className={`${activeButton === 'three' && 'active' || ''}`}
onClick={this.onButtonclick}
name="three"
disabled={activeButton !== 'one'}>
Button 2
</button>
</Component>
);
}
You can consider using button as a child component
class Button extends React.Component {
constructor(props) {
super(props);
this.setActive = this.setActive.bind(this);
}
setActive() {
this.props.onClick(this.props.value);
}
render() {
return (<button onClick={this.setActive} className={this.props.active ? 'active' : ''}>
{this.props.children}
</button>);
}
}
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
active: 0,
};
this.buttons = Array.from({ length: 5 }).map((v, index) => index);
this.setActive = this.setActive.bind(this);
}
setActive(active) {
this.setState({ active })
}
render() {
return (<div>
{
this.buttons.map((value) => (<Button key={value} value={value} active={this.state.active === value} onClick={this.setActive}>Button #{value}</Button>))
}
</div>);
}
}
Working Demo
Make your component look like below, this will work for sure:
class App extends React.Component {
constructor(props) {
super(props)
this.setActiveBackground = this.setActiveBackground.bind(this);
this.state = {
selectedCircle: {
},
};
}
setActiveBackground(name, event) {
let selected = this.state.selectedCircle;
selected = {};
selected[name] = this.state.selectedCircle[name] == "selected" ? "" : "selected";
this.setState({selectedCircle: selected});
}
render() {
return (
<div className="container">
<div className="row">
<div className="card-panel white">
<div className="center">
<p>Set Active background in selected button</p>
<button onClick={this.setActiveBackground.bind(this, "first")} className={this.state.selectedCircle["first"]}>Button 1</button>
<button onClick={this.setActiveBackground.bind(this, "second")} className={this.state.selectedCircle["second"]}>Button 2</button>
<button onClick={this.setActiveBackground.bind(this, "third")} className={this.state.selectedCircle["third"]}>Button 3</button>
</div>
</div>
</div>
</div>
);
}
}
Check demo for output

className gets removed clicking outside the div

I have the following code. By default Patriots will have btn-primary color which is blue and packers will have the default color of white. The color changes upon selection between the two buttons but when I click outside the div both button change to white. Really appreciate any suggestion. I am an absolute beginner btw.
class something {
constructor(props) {
super(props);
this.state = {
clicked: false
};
}
toggleView() {
this.setState({
clicked: true
});
}
render() {
var classRender = "btn-primary";
classRender = this.state.clicked ? "btn-primary" : "btn-primary selected ";
return (
<div>
<button
className={classRender}
type="button"
onClick={e => this.toggleView()}
>
Patriots
</button>
<button
className="btn-primary"
type="button"
onClick={e => this.toggleView()}
>
Packers{" "}
</button>
</div>
);
}
}
I just tested the code below it will update the button with selected class onClick and will keep selected if clicked outside
export default class Toggle extends Component {
constructor(props) {
super(props);
this.state = {
patriotsSelected : true
}
this.patriotsSelected = this.patriotsSelected.bind(this);
this.packersSelected = this.packersSelected.bind(this);
}
patriotsSelected(){
this.setState({patriotsSelected : true})
}
packersSelected(){
this.setState({patriotsSelected : false})
}
render() {
var patriotsClass = this.state.patriotsSelected ? "btn-primary selected" : "btn-primary";
var packersClass = this.state.patriotsSelected ? "btn-primary" : "btn-primary selected";
return (
<div>
<button className={patriotsClass} onClick={this.patriotsSelected} >
Patriots
</button>
<button className={packersClass} onClick={this.packersSelected} >
packers
</button>
</div>
);
}
}
So what's happening is even if you click the Packers button, the Patriots button still thinks it's clicked, because your assignment of 'this.state.clicked' is ambiguous in the toggleView method.
class something {
constructor(props) {
super(props);
this.state = {
clicked: null
};
}
toggleView(team) {
this.setState({
clicked: team
});
}
buttonClass(team) {
var clicked = this.state.clicked;
return (team === clicked ? "btn-primary" : "btn-primary selected ");
}
render() {
return (
<div>
<button
className={this.buttonClass('Patriots')}
type="button"
onClick={e => this.toggleView('Patriots')}
>
Patriots
</button>
<button
className={this.buttonClass('Packers')}
type="button"
onClick={e => this.toggleView('Packers')}
>
Packers{" "}
</button>
</div>
);
}
}

Resources