user1177440
user1177440

Reputation:

ReactJS - Elegant way to toggle state

I have a simple show / hide style that needs to toggle on a click event. Here is what I have:

  constructor(props) {
    super(props);
    this.state = {iover: 'hide'}
  }

  handleClick(event) {  
    // this is wrong, it returns a true or false    
    this.setState({ iover: !this.state.iover });
    // this doesn't toggle
    // this.setState({ iover: this.state.iover = 'hide' ? this.state.iover = 'show' : this.state.iover ='hide' });
    event.preventDefault()
}

I want to toggle this.state.iover value between 'show' & 'hide'.

What would be the most elegant way to do so.

Upvotes: 11

Views: 39636

Answers (6)

Manish Baral
Manish Baral

Reputation: 41

constructor(props) {
  super(props);
  this.state = {iover: false}
}

updateState = () {
  this.setState(prevState => ({
    iover: !prevState.iover
  }));
}

render() {
  return (
    <div className={this.state.iover ? 'show' : 'hide'}>...</div>
  );
}

Upvotes: 0

cristianzamar
cristianzamar

Reputation: 361

I think that @mark-anderson's answer is the most "elegant" way, however, the recommended way of doing a state toggling (according to React docs) is:

this.setState(prevState => ({
  iover: !prevState.iover
}));

*If you need to store 'show/hide' inside that state, the code would be:

this.setState(prevState => ({
  iover: prevState.iover === 'hide' ? 'show' : 'hide'
}));

Upvotes: 7

user8290176
user8290176

Reputation: 41

Although this was a little challenge for me but I ended up like this --

class Toggle extends React.Component{

constructor(props){
    super(props);
    this.handleToggleVisib = this.handleToggleVisib.bind(this);
    this.state = {
         visib : false 
    }
}

handleToggleVisib(){
    this.setState({ visib : !this.state.visib });
}

render(){
    return(
        <div>
        <h1>Toggle Built</h1>
        <button onClick={this.handleToggleVisib}>
        {this.state.visib? 'Hide Button' : 'Show Button'}
        </button>
        <div>
        {this.state.visib && <p>This is a tough challenege</p>}
        </div>
        </div>
      );
    }
}

 ReactDOM.render(<Toggle />,document.getElementById('app'));

Upvotes: 1

roheyd
roheyd

Reputation: 1

There's a really handy little utility for React called classnames (https://github.com/JedWatson/classnames)

It lets you conditionally render a class, which you can use to handle add the style you need for hiding/showing.

For example, here I'm toggling the state with a function:

state = {
    isOpen: false
}

toggleDropdown = () => {
    const toggledIsOpen = this.state.isOpen ? false : true;

    this.setState({
        isOpen: toggledIsOpen
    });
}

Then, in the onClick handler for my dropdown , I use classnames to either print class="dropdown" or class="dropdown is-open":

// conditionally add 'is-open' class for styling purposes
   const openClass = classNames("dropdown", {
        "is-open": isOpen
   });


return (
    <div className={openClass} onClick={this.toggleDropdown}>[dropdown contents here]</div>
);

Upvotes: 0

Mark Anderson
Mark Anderson

Reputation: 663

One way to do this is to keep your state as a boolean true or false then put a ternary operator wherever you want the value "hide" or "show". For example:

  getInitialState: function() {
    return {
      iover: false
    };
  },

  handleClick: function() {
    this.setState({
      iover: !this.state.iover
    });
  },

  render: function(){
    return (
      <div className={this.state.iover ? 'show' : 'hide'}>...</div>
    );
  }

Upvotes: 16

user1177440
user1177440

Reputation:

This is the best I could come up with, was hoping for something shorter:

    handleClick(event) {
      let show = this.state.iover;
      let index = show.indexOf('show');

      if (index != -1) {
          show = 'hide';
      } else {
          show = 'show';
      }

      this.setState({ iover: show });
      event.preventDefault()
}

Upvotes: -1

Related Questions