最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to handle state of multiple buttons with react? - Stack Overflow

programmeradmin3浏览0评论

I have a bootstrap grid where each grid item is populated from an array of objects but after each grid item I would like to have a vote button. How could I achieve this with maintaining state on each button separately, ie when button 1 is clicked the text should change from 'vote' to 'voted' whilst the others remain as 'vote'.

At the moment when a button is clicked, all of them change to 'Voted'

class Items extends Component {
    constructor(props) {
        super(props);
        this.state = { hasVoted: false };

        this.OnClick = this.OnClick.bind(this);
    }

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

    render() {
        const Item = teasers.items.map(item =>
            <Col key={item.nid}>
                <span>
                    {itemType}
                </span>

                <a href={item.path}>
                    <Image src={item.image.src} title={item.productType} />
                    <span>
                        {item.Title}
                    </span>
                    <div className={teasersStyle.copy}>
                        {" "}{item.Copy}>
                    </div>
                </a>

                <div
                    className={this.state.hasVoted ? "active" : "notactive"}
                    onClick={this.OnClick}
                >
                    {this.state.hasVoted ? "Voted" : "Vote"}
                </div>
            </Col>
        );
        return (
            <div>
                <Grid>
                    <Row>
                        {Item}
                    </Row>
                </Grid>
            </div>
        );
    }
}

export default Items;

I have a bootstrap grid where each grid item is populated from an array of objects but after each grid item I would like to have a vote button. How could I achieve this with maintaining state on each button separately, ie when button 1 is clicked the text should change from 'vote' to 'voted' whilst the others remain as 'vote'.

At the moment when a button is clicked, all of them change to 'Voted'

class Items extends Component {
    constructor(props) {
        super(props);
        this.state = { hasVoted: false };

        this.OnClick = this.OnClick.bind(this);
    }

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

    render() {
        const Item = teasers.items.map(item =>
            <Col key={item.nid}>
                <span>
                    {itemType}
                </span>

                <a href={item.path}>
                    <Image src={item.image.src} title={item.productType} />
                    <span>
                        {item.Title}
                    </span>
                    <div className={teasersStyle.copy}>
                        {" "}{item.Copy}>
                    </div>
                </a>

                <div
                    className={this.state.hasVoted ? "active" : "notactive"}
                    onClick={this.OnClick}
                >
                    {this.state.hasVoted ? "Voted" : "Vote"}
                </div>
            </Col>
        );
        return (
            <div>
                <Grid>
                    <Row>
                        {Item}
                    </Row>
                </Grid>
            </div>
        );
    }
}

export default Items;
Share Improve this question edited Jul 31, 2017 at 22:46 Andrii Starusiev 7,7642 gold badges30 silver badges39 bronze badges asked Jul 31, 2017 at 16:00 Chris OChris O 7222 gold badges9 silver badges20 bronze badges 3
  • Make hasVoted a property of each item. – Ingo Bürk Commented Jul 31, 2017 at 16:03
  • @IngoBürk Not sure I understand exactly what you mean. Like this: hasVoted = { this.state.hasVoted } – Chris O Commented Jul 31, 2017 at 16:10
  • You can either make your buttons stateful or you can store their hasVoted state in Items state as an array of booleans with an index that matches the button's index within teasers.items. Then when you map teasers.items.map((item, index) =>{...}), you can use the index to access the hasVoted state and apply the property to the button. As an aside: You're using this.handleOnClick but your method is named OnClick(). – Kyle Richardson Commented Jul 31, 2017 at 16:10
Add a comment  | 

1 Answer 1

Reset to default 17

I have created a simple example for you:

class App extends React.Component {
    constructor() {
        super();
        this.onClick = this.onClick.bind(this);
        this.state = {
            arr: [
                { name: "first", isActive: true },
                { name: "second", isActive: true },
                { name: "third", isActive: true },
                { name: "fourth", isActive: true }
            ]
        };
    }
    onClick(index) {
        let tmp = this.state.arr;
        tmp[index].isActive = !tmp[index].isActive;
        this.setState({ arr: tmp });
    }
    render() {
        return (
            <div>
                {this.state.arr.map((el, index) =>
                    <div key={index} onClick={() => this.onClick(index)}>
                        name: {el.name} / isActive: {el.isActive ? "true" : "false"}
                    </div>
                )}
            </div>
        );
    }
}

Check the fiddle and implement it in your case.

One more way to handle this is keeping the index of an active button in the state:

class App extends React.Component {

state = {
    users: [
    { name: "John" },
    { name: "Sarah" },
    { name: "Siri" },
    { name: "Jim" },
    { name: "Simon" },
  ],
  activeIndex: 0,
}

render() {
    const { users, activeIndex } = this.state;

    return (
      <div>
        {users.map((u, i) => (
          <div
            className={i === activeIndex ? 'active' : ''}
            onClick={() => this.setState({ activeIndex: i })}
            key={u.name}
          >
            {u.name}
          </div>
        ))}
      </div>
    )
  }
}

https://jsfiddle.net/846tfe3u/

发布评论

评论列表(0)

  1. 暂无评论