简体   繁体   中英

How can I toggle only one button at a time onclick?

I'd like to know how I'd be able to toggle one button to green color one at a time onclick. With my current code, when I click on one (with the intention of toggling one of them green), it toggles the other three buttons green as well.

Note: white-btn and green-btn are CSS classes that I've defined.

I've made too many attempts to list here to try and rectify this. What am I doing wrong?

constructor(props) {
    super(props);
    this.state = {
        white: true,
        smallSize: false,
        mediumSize: false,
        largeSize: false,
        xLargeSize: false,
    };
    this.smallClicked = this.smallClicked.bind(this);
    this.mediumClicked = this.mediumClicked.bind(this);
    this.largeClicked = this.largeClicked.bind(this);
    this.xLargeClicked = this.xLargeClicked.bind(this);
}

smallClicked() {
    console.log("clicked small");
    this.setState({smallSize: true, mediumSize: null, largeSize: null, xLargeSize: null, white: !this.state.white});
}

mediumClicked() {
    console.log("clicked medium");
    this.setState({mediumSize: true, smallSize: null, largeSize: null, xLargeSize: null, white: !this.state.white});
}

largeClicked() {
    console.log("clicked large");
    this.setState({largeSize: true, smallSize: null, mediumSize: null, xLargeSize: null, white: !this.state.white});
}

xLargeClicked() {
    console.log("clicked x-large");
    this.setState({xLargeSize: true, smallSize: null, mediumSize: null, largeSize: null, white: !this.state.white});
}

render() {
    let color_switch_size = this.state.white ? "white-btn" : "green-btn";

   return(
     <button className={color_switch_size} onClick={this.smallClicked}>Small</button>
     <button className={color_switch_size} onClick={this.mediumClicked}>Medium</button>
    <button className={color_switch_size} onClick={this.largeClicked}>Large</button>
   <button className={color_switch_size} onClick={this.xLargeClicked}>X-Large</button>
   );
}

A way to do that is to have a class for handling the clicked state, eg, 'greenClas'.

For each button, you add that class in case it has been clicked or not.

 return(
     <button className={`buttonClass ${this.state.smallSize} ? 'greenClass' : ''`} onClick={this.smallClicked}>Small</button>

... 

   );

I'd change a few things about how this is structured. I'd use a single change handler, and not use the white variable anymore.

Here's my suggestion:

const initialValues = {
  small: false,
  medium: false,
  large: false,
  x_large: false,
};

.....

constructor(props) {
  super(props);
  this.state = {...initialValues};
}

// We'll use a generic handler that receives the button name
handleClick = (button) => (e) => {
  // Update the button to be the opposite of what it was before
  this.setState({[button]: !this.state[button]});

  // OR

  // If you want to restrict it to one white button at a time
  this.setState({
    ...initialValues,
    [button]: !this.state[button]
  });
}

// Separate this into its own function to keep render cleaner
getClassName = (button) => {
  // if button is set to true, use white
  if (this.state[button]) {
    return "white-btn";
  }
  // else use green
  return "green-btn";
}

render() {
  // Now each button has its class name managed independently
  return(
    <>
      <button 
        className={this.getClassName('small')}
        onClick={this.handleClick('small')}
      >
        Small
      </button>
      <button 
        className={this.getClassName('medium')} 
        onClick={this.handleClick('medium')}
      >
        Medium
      </button>
      <button
        className={this.getClassName('large')} 
        onClick={this.handleClick('large')}
      >
        Large
      </button>
      <button 
        className={this.getClassName('x_large')} 
        onClick={this.handleClick('x_large')}
      >
        X-Large
      </button>
    </>
   );
}

Here is my idea. I just add a small condition to verify the button before applying the style

constructor(props) {
    super(props);
    this.state = {
      white: true,
      smallSize: false,
      mediumSize: false,
      largeSize: false,
      xLargeSize: false
    };
    this.smallClicked = this.smallClicked.bind(this);
    this.mediumClicked = this.mediumClicked.bind(this);
    this.largeClicked = this.largeClicked.bind(this);
    this.xLargeClicked = this.xLargeClicked.bind(this);
  }

  smallClicked() {
    console.log("clicked small");
    this.setState({
      smallSize: true,
      mediumSize: null,
      largeSize: null,
      xLargeSize: null,
      white: !this.state.white
    });
  }

  mediumClicked() {
    console.log("clicked medium");
    this.setState({
      mediumSize: true,
      smallSize: null,
      largeSize: null,
      xLargeSize: null,
      white: !this.state.white
    });
  }

  largeClicked() {
    console.log("clicked large");
    this.setState({
      largeSize: true,
      smallSize: null,
      mediumSize: null,
      xLargeSize: null,
      white: !this.state.white
    });
  }

  xLargeClicked() {
    console.log("clicked x-large");
    this.setState({
      xLargeSize: true,
      smallSize: null,
      mediumSize: null,
      largeSize: null,
      white: !this.state.white
    });
  }

  render() {
    let color_switch_size = this.state.white ? "white-btn" : "green-btn";

    return (
      <React.Fragment>
        <button
          className={this.state.smallSize && color_switch_size}
          onClick={this.smallClicked}
        >
          Small
        </button>
        <button
          className={this.state.mediumSize && color_switch_size}
          onClick={this.mediumClicked}
        >
          Medium
        </button>
        <button
          className={this.state.largeSize && color_switch_size}
          onClick={this.largeClicked}
        >
          Large
        </button>
        <button
          className={this.state.xLargeSize && color_switch_size}
          onClick={this.xLargeClicked}
        >
          X-Large
        </button>
      </React.Fragment>
    );
  }
this.state = {
    small: true,
    medium: true,
    large: true,
    xLarge: true,
}

changeColor = event => {
    this.setState({ [event.target.name]: !this.state[event.target.name] });
}

getButtons = () => {
    const sizes = ['small', 'medium', 'large', 'xlarge'];
    return sizes.map(size => <button className={this.state[size] ? 'white-btn' : 'green-btn'} onClick={this.changeColor} name={size}>{size.toCamelCase()}</button>)
}

render() {
    return (
        <div>
            {this.getButtons()}
        </div>
    )
}

I think you can achieve that like that a much easier way. Would that solution work for you?

    constructor(props) {
    super(props);
    this.state = {
      smallSize: false,
      mediumSize: false,
      largeSize: false,
      xLargeSize: false
    };
  }

  onButtonPress = buttonName => {
    console.log('clicked  ' + buttonName);
    let myButtonsState = this.state;
    myButtonsState[buttonName] = !myButtonsState[buttonName];
    this.setState({
      ...myButtonsState
    });
  };

  render() {

    return (
      <View>
        <button
          className={this.state.smallSize ? 'white-btn' : 'green-btn'}
          onClick={() => this.onButtonPress('smallSize')}
        >
          Small
        </button>
        <button
        className={this.state.mediumSize ? 'white-btn' : 'green-btn'}
          onClick={() => this.onButtonPress('mediumSize')}
        >
          Medium
        </button>
        <button
        className={this.state.largeSize ? 'white-btn' : 'green-btn'}
          onClick={() => this.onButtonPress('largeSize')}
        >
          Large
        </button>
        <button
        className={this.state.xLargeSize ? 'white-btn' : 'green-btn'}
          onClick={() => this.onButtonPress('xLargeSize')}
        >
          X-Large
        </button>
      </View>
    );
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM