在 React 中,对于一组按钮,如何在单击后更改颜色同时记录单击了哪个 button/buttons is/are?

in React for an array of buttons, how to change color after click while also record which button/buttons is/are clicked?

我有一个子组件,它是一个按钮,点击后颜色会随着状态更新而改变。但是,我还需要在一组这样的按钮中识别正在单击的按钮。 sandbox 或以下的代码。我该怎么做?如果我对子组件有操作,那么如何正确调用父组件的onclick?

button.js

import React, { Component } from 'react';
import './style.css'

class Button extends React.Component {
    constructor(props){
        super(props);

        this.state = {
           clicked: false
        }
    }

    changeColor=()=>{
       this.setState({clicked: !this.state.clicked})
    }

    render(){
        let btn_class = this.state.clicked ? "redButton" : "whiteButton";

        return (
             <button className={btn_class} onClick={this.changeColor.bind(this)}>
                  {this.props.name}
             </button>
        )
    }
}
export default Button;

index.js

import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
import Button from './button.js'

const btns= ['button1','button2','button3']
const n = btns.length

class App extends Component {
  constructor() {
    super();
    this.state = {
      clickedBtn : "",
      btnStyle: new Array(n)
    };
  }

handleClick= (index) => 
  {
    alert(index)
  }

  render() {
    return (
      <div>
            {btns.map((btn, index) => (
                      <Button 
                        name={btn} 
                        onClick={this.handleClick.bind(this,index)}/>
                    ))}
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

您可以尝试类似的操作,最后您将在 clickedButton 对象中获得单击按钮值。

import React, { Component } from 'react';
import './style.css'

class Button extends React.Component {
    constructor(props){
        super(props);

        this.state = {
           clicked: false
        }
    }

    changeColor=()=>{
       this.setState({clicked: !this.state.clicked})
this.props.onButtonClick(this.props.index)
    }

    render(){
        let btn_class = this.state.clicked ? "redButton" : "whiteButton";

        return (
             <button className={btn_class} onClick={this.changeColor.bind(this)}>
                  {this.props.name}
             </button>
        )
    }
}
export default Button;

index.js

class App extends Component {
      constructor() {
        super();
        this.state = {
          clickedBtn : {},
          btnStyle: new Array(n)
        };
      }

    handleClick= (index) => 
      {
        let clickedBtn = this.state.clickedBtn 
        if(clickedBtn[index]){
           delete clickedBtn[index]
        } else{
           clickedBtn[index]= true
        }
      }

      render() {
        return (
          <div>
                {btns.map((btn, index) => (
                          <Button 
                            name={btn} 
                        index={index}
                         onButtonClick={this.handleClick}/>
                        ))}
          </div>
        );
      }
    }

    render(<App />, document.getElementById('root'));

您可以为此使用通用处理函数。现在也没有理由将方法绑定到 class - 如果您使用箭头函数来定义您的代码,则不再需要这样做方法。

最后,您可能应该使用 setState 提供的回调来调用 Button 组件内的 onClick 属性。

更多关于setState回调:你使用回调的方式是这样的:

setState({ some: "newState"}, function() { /* this is the callback function */ })

使用setState回调:

class Button extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      clicked: false
    };
  }

  handleClick = event => {
    this.setState({ 
      clicked: !this.state.clicked 
    }, () => { // Should prob use the callback that setState provides
      if (this.props.onClick) this.props.onClick() 
    });
  };

  render() {
    let btn_class = this.state.clicked ? "redButton" : "whiteButton";

    return (
      <button className={btn_class} onClick={this.handleClick}>
        {this.props.name}
      </button>
    );
  }
}

const btns= ['button1','button2','button3']
const n = btns.length

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      clickedBtn: "",
      btnStyle: new Array(n)
    };
  }

  handleClick = index => {
    alert(index);
  };

  render() {
    console.log(this.state.clickedTag);
    return (
      <div>
        {btns.map((btn, index) => (
          <Button name={btn} onClick={() => this.handleClick(index)} />
        ))}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
h1, p {
  font-family: Lato;
}

.whiteButton{
  background-color: white
}

.redButton{
  background-color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>


不使用 setState 回调:

class Button extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      clicked: false
    };
  }

  handleClick = event => {
    this.setState({ 
      clicked: !this.state.clicked 
    });
    if (this.props.onClick) this.props.onClick()     
  };

  render() {
    let btn_class = this.state.clicked ? "redButton" : "whiteButton";

    return (
      <button className={btn_class} onClick={this.handleClick}>
        {this.props.name}
      </button>
    );
  }
}

const btns= ['button1','button2','button3']
const n = btns.length

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      clickedBtn: "",
      btnStyle: new Array(n)
    };
  }

  handleClick = index => {
    alert(index);
  };

  render() {
    console.log(this.state.clickedTag);
    return (
      <div>
        {btns.map((btn, index) => (
          <Button name={btn} onClick={() => this.handleClick(index)} />
        ))}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
h1, p {
  font-family: Lato;
}

.whiteButton{
  background-color: white
}

.redButton{
  background-color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>