ErikK
ErikK

Reputation: 179

React: Why is element style not toggling with setState?

It's just a simple toggle mechanism:

Onclick of the element is to toggle a border color change by responding to state change. It changes the color once! But won't toggle back to original color.

(I've experimented with so many variations of the functionality, read/reread React docs on state, setState's asynchronous/batch change functionality, and combed SO again-and-again.)

Can someone help me find a solution?

Thanks in advance!

import React, { Component } from 'react';

class Button extends Component {
  constructor(props) {
    super(props);
    this.state = {
      active: false,
    }
    this.updateActive = this.updateActive.bind(this);
  }



 updateActive(){
    this.setState(function(){
      this.state.active = !this.state.active;
      { return this.state.active; }
    });
  }

  render(){
    return (
      <div className="seq_btn" onClick={this.updateActive} style={ {borderColor: this.state.active ? 'black' : 'rgb(193, 255, 112)' }}></div>
    )
  }
}

export default Button;

Upvotes: 0

Views: 608

Answers (2)

Joshua Underwood
Joshua Underwood

Reputation: 927

As a matter of good habit, you should never mutate state in any form that isn't directly performed with setState

Even using

this.state.active = !this.state.active

is bad form and is most likely your issue.

Instead consider

this.setState({ active: !this.state.active });

Also understand that setState's can be batched for processing later, they are not always immediately executed.

setState() does not always immediately update the component. It may batch or defer the update until later.

https://reactjs.org/docs/react-component.html#setstate

As noted below, a functional component would serve the same purpose without the overhead of lifecycle methods

import React from "react";

const Button = ({ active, clickAction }) => (
    <div onClick={clickAction} className={{ borderColor: active ? "green": "purple"}}>
</div>);

export default Button;

Upvotes: 0

Andy Ray
Andy Ray

Reputation: 32076

Because your return syntax is incorrect:

this.setState(function(){
  this.state.active = !this.state.active;
  { return this.state.active; }
});

This should be:

this.setState(function(){
  return { active: !this.state.active };
});

However, you don't need to use the callback here at all. You should just setState with the new data.

this.setState({ active: !this.state.active });

Upvotes: 1

Related Questions