Switch between different button styles when a button is clicked in a React application

I am looking to update the appearance of buttons when they are clicked.

Here is a preview of my files:

MainApp.js:

class ChangeButton extends Component {
  constructor(){
         super();
         this.state = {
              black: true
         }
    }
    changeColor(){
        this.setState({black: !this.state.black})
    }
    render(){
        let btn_class1 = this.state.black ? "blackButton" : "whiteButton";
        let btn_class2 = this.state.black ? "whiteButton" : "blackButton";
        let btn_class3 = this.state.black ? "whiteButton" : "blackButton";

        return (
             <div>
                 <button className={btn_class1}
                         onClick={this.changeColor.bind(this)}>
                           Button1
                  </button>
                  <button className={btn_class2}
                         onClick={this.changeColor.bind(this)}>
                           Button2
                  </button>
                  <button className={btn_class3}
                         onClick={this.changeColor.bind(this)}>
                           Button3
                  </button>
             </div>
        )
    }
}
export default MainApp;

design.css:

button{
  width: 80px;
  height: 40px;
  margin: 15px;
}
.blackButton{
  background-color: black;
  color: white;
}

.whiteButton{
  background-color: white;
  color: black;
}

Initially, I want button1 to have a black background while button2 and button3 should have a white background.

Upon clicking button2, it should switch to a black background, with button1 and button3 changing to a white background.

Similarly, when pressing button3, it should turn to a black background, shifting button1 and button2 to have a white background.

Answer №1

Approach 1
To manage the dark button state, a simple method is to create a state variable that stores the name of the currently dark button. Then, on button click events, pass the button name to a function that updates the state with the new dark button's name. This approach ensures only one button remains dark at a time.
Subsequently, compare each button's name with the darkButton state to determine whether it should have the dark or light class applied.

class Test extends Component {
  constructor() {
    super();
    this.state = {
      darkBtn: "btn1"
    };
  }

  changeColor = (btn) => {
    this.setState({ darkBtn: btn });
  };

  addDarkClass = (btn) => {
    if (this.state.darkBtn === btn) return "blackButton";
    else return "whiteButton";
  };

  render() {
    return (
      <div>
        <button
          className={this.addDarkClass("btn1")}
          onClick={this.changeColor.bind(this, "btn1")}
        >
          Button1
        </button>
        <button
          className={this.addDarkClass("btn2")}
          onClick={this.changeColor.bind(this, "btn2")}
        >
          Button2
        </button>
        <button
          className={this.addDarkClass("btn3")}
          onClick={this.changeColor.bind(this, "btn3")}
        >
          Button3
        </button>
      </div>
    );
  }
}

export default Test;



The above code snippet demonstrates how to toggle between dark and light classes for buttons based on the darkButton state in React.

Approach 2
If the buttons share similar properties, utilizing the map function can simplify the coding process.

class Test extends Component {
  constructor() {
    super();
    this.state = {
      darkBtn: 0
    };
  }

  changeColor = (btn) => {
    this.setState({ darkBtn: btn });
  };

  btns = ["Button1", "Button2", "Button3"];

  render() {
    return (
      <div>
        {this.btns.map((btn, i) => (
          <button
            key={i}
            onClick={this.changeColor.bind(this, i)}
            className={this.state.darkBtn === i ? "blackButton" : "whiteButton"}
          >
            {btn}
          </button>
        ))}
      </div>
    );
  }
}

export default Test;

Answer №2

You have the option to simplify the process by utilizing state. Start by using state to store the index of the currently active button. Then, create an array of any desired size and iterate over it using the .map function to generate your buttons. The active button should be identified by matching its index with the active variable in the state.

class Test extends Component {
  constructor(){
         super();
         this.state = {
              active: 0
         }
    }
    changeColor = (i) => {
        this.setState({active: i})
    }
    render(){
        return (
             <div>
                 {Array.apply(null, Array(3)).map((el, i) => {
                 const active = this.state.active === i
                 <button key={i} className={active ? 'blackButton' : 'whiteButton'}
                         onClick={() => this.changeColor(i)}>
                           `Button${i + 1}`
                  </button>
             </div>
        )
    }
}
export default App;

Answer №3

Functioning well

import React, { useState } from 'react';   
import './App.css';
const App = () => {
  const [counter, setCounter] = useState(0);

  const displayButtons = () => {
    return [0, 1, 2].map(item => {
      return <button 
      className={item === counter ? 'activeButton': 'inactiveButton'} 
      onClick={()=> setCounter(item)}
      key={item} > {`Button${item+1}`} </button>
    })
  }

  return (
    <div>
      {displayButtons()}
    </div>
  )
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to modify the CSS for the product quantity display on my Shopify cart?

It has come to my attention that when accessing my shopping cart from a mobile device, the quantities of items ordered are not visible if the product names are lengthy. Instead, only the product names and prices are displayed, requiring me to scroll in o ...

Space left vacant following an unordered list item

Is there a way to remove unwanted space after an unordered list in IE and Firefox, specifically in the last HTML <li> item? I've tried adjusting the ul width but it didn't work. Any ideas on how to get rid of the space? Thanks. #menubar ...

Tips for making sure there is a delay in between each axios call in a React

Currently in the process of developing an application that needs to interact with a RestAPI by sending a specific set of inputs. However, the API has a major flaw when it comes to scalability and tends to respond with code 429 if bombarded with too many re ...

Managing schedules for tasks

I am currently working on a project involving a pet feeder using React-Native for the app, Node.js for the server, and Arduino (ESP32). However, I am struggling to find a way to automate food drops at specific times. I have explored libraries like node-sc ...

Clicking on the div will set focus in the input field

Inside my function component, I have the following HTML structure: <div> <input /> <div> <div> <input /> <div> <div> <input /> <div> I am struggling to find a simple solution for this... I ca ...

Div flexes and compresses smaller than its content dimensions

Here's a link to the fiddle: check it out Take a look at a normal card below: https://i.sstatic.net/7Yqqv.png But when the browser window is resized, it shrinks to this: https://i.sstatic.net/1aexK.png This is the HTML structure: #product-list ...

Develop interactive applications with React Native by generating N animated values

Currently, I am in the process of developing a component known as a "Color Palette," which includes a prop called "paletteColors." The "paletteColors" prop is an array with varying lengths that houses color values represented as strings. Within this comp ...

Saving moveable objects on a Kanban board to firebase

As part of my project, I have developed a Kanban Board with 3 columns - To Do, Doing, and Done. Each column is populated with tasks, and I have successfully linked actions such as adding, deleting, and modifying tasks and columns to Firebase. However, ther ...

Is there a method to trigger the DOM style change hook without using asynchronous code?

We have learned that css animation/transition does not work with display: block&display: none; therefore, I attempted to use someDom.style.transition = '0.3s' someDom.style.display='block' someDom.style.opacity=1 to create an anim ...

Refreshing backdrop for navigating through lists - Sprite edition

I am facing some issues while trying to use a sprite image for my navigation icons. The background position offset is not working as expected, and the background image is stretching across the whole length of the navigation. It seems like I may need to spe ...

Is there a method to determine the page location of a DOM element when the body has a relative position?

I came across an unusual bug that started popping up when I set the body as a relatively positioned element with a 39px margin (to accommodate a toolbar at the top of a page). Typically, when you refer to guides on calculating the position of a page eleme ...

"Enhancing the appearance of the input component in a TextField by utilizing the styled function

Looking to customize the appearance of the MUI TextField component using a styled function: const StyledTextField = styled(TextField)({ padding: 5 }); Interested in also styling the Input and input components within the TextField. In the past, this was ac ...

Checking if the text in view is completely visible using Selenium

Is it possible to verify with Selenium whether a text is completely visible? For example, if I have the text: lorum ipsum dolor sit amet and due to incorrect CSS styling, only part of it appears on the page: lorem ips while the rest is hidden under ...

A guide on using FileReader to efficiently read multiple images

I need to be able to select multiple images from one input and read them using File Reader. If I leave it as is, it only gives me one picture. const [image , setImage] = useState(''); const [imageSelected , setImageSelected] = useState(nul ...

Design featuring overlaying text on an image

Looking to add a triangle with text over an image using CSS? Here's a sample image for reference: Here's what I have so far: .image { background: url('../image.jpg'); background-repeat: no-repeat; background-size: cover; ...

Position the v-switch in the center of a v-flex container

I need to center the v-switch element inside a v-flex horizontally, but my attempts based on guidance from this post on vuetify center items into v-flex have been unsuccessful for the v-switch element. Even when I wrap it in a div with a class like below: ...

Creating thumbnails for documents, like in Google Docs, using NextJS

For my personal project, I am working on creating a Google Docs clone using Quill and NextJS. As part of this project, I want to have thumbnails for all the documents displayed, similar to Google Docs. I initially tried displaying the first 100 characters ...

Looking for advice on using media queries to resize my background image - any tips?

I'm struggling to resize my background image using media queries. Can anyone offer suggestions or solutions? I've tried applying the media query for my background image like I do with other elements, and it's not working properly. The issue ...

A step-by-step guide to extracting targeted information from an API and showcasing it within a React Native Flatlist

I'm currently developing a React Native application that will display all live and upcoming coding contests using an API. Here are some sample results from the API: Object { "duration": "1209300.0", "end_time": " ...

Position fixed causing website header to hide behind content

As I work on creating a website for a school, I aim to have a fixed header similar to what can be seen on Facebook. Despite trying out some fixes mentioned in this Stack Overflow [question][1], I am struggling to make it work effectively in my design. The ...