Home > OS >  Toggle class on button click in react js using state without re rendering component
Toggle class on button click in react js using state without re rendering component

Time:09-16

I am trying to change the class of a button in react js on click using hooks. The problem is when the class toggle happens through a state change, the result of the class toggle is seen but the page re-renders, rendering the initial class (not the one that is toggled to). Please help

Buttons

<button className={buttonColor1?styles.priceButtonWhite:styles.priceButtonGreen} onClick={() => changeColor(1)}>100</button>
<button className={buttonColor2?styles.priceButtonWhite:styles.priceButtonGreen} onClick={() => changeColor(2)}>200</button>
<button className={buttonColor3?styles.priceButtonWhite:styles.priceButtonGreen} onClick={() => changeColor(3)}>300</button>

Change Color Function

const changeColor = (n) => {
        if (n==1){
            setButtonColor1(!buttonColor1);
        }
        else if (n==2){
            setButtonColor2(!buttonColor2);
        }
        else{
            setButtonColor3(!buttonColor3 );
        }
    }

Hooks

const [buttonColor1, setButtonColor1] = useState(true);
const [buttonColor2, setButtonColor2] = useState(true);
const [buttonColor3, setButtonColor3] = useState(true);

SCSS

.priceButton{
    border-radius: 10px;
    padding: 10px;
    border: none;
}
.priceButtonWhite{
    @extend .priceButton;
    background: white;
    border: 1px solid #166C6C;
}
.priceButtonGreen{
    @extend .priceButton;
    background: #166C6C;
}

On button click, the class gets toggled to priceButtonGreen, then the entire page re-renders leaving the class priceButtonWhite on the buttons

CodePudding user response:

I created a working example here: https://codesandbox.io/s/suspicious-curie-90t4c?file=/src/App.js

Since the style object is missing in your example It's hard to see what is the mistake in your code.

function Toggler() {
  const [buttonColor1, setButtonColor1] = useState(true);
  const [buttonColor2, setButtonColor2] = useState(true);
  const [buttonColor3, setButtonColor3] = useState(true);

  return (
    <div>
      <button
        className={`priceButton ${
          buttonColor1 ? "priceButtonWhite" : "priceButtonGreen"
        }`}
        onClick={() => setButtonColor1(!buttonColor1)}
      >
        100
      </button>
      <button
        className={`priceButton ${
          buttonColor2 ? "priceButtonWhite" : "priceButtonGreen"
        }`}
        onClick={() => setButtonColor2(!buttonColor2)}
      >
        200
      </button>
      <button
        className={`priceButton ${
          buttonColor3 ? "priceButtonWhite" : "priceButtonGreen"
        }`}
        onClick={() => setButtonColor3(!buttonColor3)}
      >
        300
      </button>
    </div>
  );
}
.priceButton {
  border-radius: 10px;
  padding: 10px;
  border: none;
}

.priceButtonWhite {
  background: white;
  border: 1px solid #166c6c;
}

.priceButtonGreen {
  background: #166c6c;
}

Within the structure you proposed this is a working solution.

CodePudding user response:

When you have button element inside form element then clicking on a button will cause the page to reload (button element has type attribute set to submit by default).

You can either change the type of a button to button or use event.preventDefault() in the button listener.

  • Related