Alyssa
Alyssa

Reputation: 55

Changing the className of a button based on state isn't working properly

I am trying to change the CSS of a button based on whether or not it's active in state. For some reason, the className is not showing up in my HTML even though I am assigning it the value of the ternary conditional.

  var [isActive] = useState(false);
  var [btn_class] = useState('');

  const addOrRemove = (array, value) => {
    var index = array.indexOf(value);

    if (index === -1) {
      array.push(value);
      isActive = !isActive;
    } else {
      array.splice(index, 1);
      isActive = !isActive;
    }
    btn_class = isActive ? 'noBackground' : 'background';
  };

   <div>
            <Button
              onClick={e => addOrRemove(formData.interests, e.target.value)}
              value="Front-End Engineering"
              className={btn_class}
            >
              Front-End Engineering
            </Button>
            <Button
              onClick={e => addOrRemove(formData.interests, e.target.value)}
              value="Back-End Engineering"
              className={btn_class}
            >
              Back-End Engineering
            </Button>
          </div>

I'm looking for something exactly like this, but that approach isn't working.

https://jsfiddle.net/tkkqx2y2/

Upvotes: 2

Views: 114

Answers (2)

Lu&#237;s Ramalho
Lu&#237;s Ramalho

Reputation: 10208

You could keep the state for each button, like so:

var [frontend, setFrontend] = useState({
  isActive: true
});
var [backend, setBackend] = useState({
  isActive: true
});

and then set it onClick:

<div>
  <Button
    onClick={e => {
      setFrontend({ ...frontend, isActive: !frontend.isActive });
      addOrRemove(formData.interests, e.target.value);
    }}
    value="Front-End Engineering"
    className={frontend.isActive ? "noBackground" : "background"}
  >
    Front-End Engineering
  </Button>
  <Button
    onClick={e => {
      setBackend({ ...backend, isActive: !backend.isActive });
      addOrRemove(formData.interests, e.target.value);
    }}
    value="Back-End Engineering"
    className={backend.isActive ? "noBackground" : "background"}
  >
    Back-End Engineering
  </Button>
</div>

You probably can refactor the above based on the rest of your code, but the main idea is that you'll have to keep at least two states (it can be in the same useState, like {first: true, second: true}, one for each button.

You cannot have a shared state, otherwise when you change on one button it will change the other because they'll be using the exact same state.

You'll have to see how to structure your state in your particular app.

Upvotes: 1

jakeduck
jakeduck

Reputation: 56

As per the docs, you need a setter function to change the state.

Your state declarations would look like: const [isActive, setIsActive] = useState(false); and in your addOrRemove function, call setIsActive(!isActive);

Upvotes: 2

Related Questions