简体   繁体   English

如何更改数组中受onClick影响的项目的状态?

[英]How to change the state of an item affected by onClick in array?

I'm making a page where I need to make multiple selections of buttons (like a filter, which I'll use for the next page). 我正在制作一个页面,需要在其中选择多个按钮(例如过滤器,将在下一页中使用它)。

the information from these buttons is coming from an array and I'm using .map () to mount the button list. 这些按钮的信息来自数组,我正在使用.map()挂载按钮列表。

My problem is how do I change the state of only the button that was clicked. 我的问题是如何更改仅单击的按钮的状态。 The way it is now, when I click, all the buttons are active. 现在,当我单击时,所有按钮都处于活动状态。

How can I solve this? 我该如何解决?

Thank you. 谢谢。

import React from 'react';
import { Link } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
import messages from './messages';

import { getLevel, getDiscipline } from '../../functions';

import template from './index.pug';

export default class ConfigAssessment extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function

  constructor(props){
    super(props);
    this.state = {
      level: getLevel(),
      discipline: getDiscipline(),
      active: '',
      first_click: true,
    }
  }

  changeActive = () => {
    if (this.state.first_click === true) {
      this.setState({
        active: 'active',
        first_click: false
      });
    } else {
      this.setState({
        active: '',
        first_click: true,
      });
    }
  }


  render() {
    return(
<div className="configuration">
      <div className="config-title">
        <i className="ti-settings" />
        <h2>
          <FormattedMessage {...messages.configAssessment} />
        </h2>
      </div>
      <div className="config-items">
        <div className="form-group">
          <label>
            <FormattedMessage {...messages.level} />
          </label>
          <div className="row">
            {this.state.level.map((level, i) => (
              <div className="col-xs-1 col-md-4 col-lg-3" key={level.id}>
                <button
                  className={`btn btn-light-gray btn-block ${this.state.active}`}
                  id={level.id}
                  onClick={this.changeActive}
                >
                  {level.level}
                </button>
              </div>
              ))}
          </div>
        </div>
        <div className="form-group">
          <label>
            <FormattedMessage {...messages.discipline} />
          </label>
          <div className="row">
            { this.state.discipline.map((discipline, i) => (
              <div className="col-xs-1 col-md-4 col-lg-3" key={i}>
                <button
                  className={`btn btn-light-gray btn-block ${this.state.active}`}
                  onClick={this.changeActive}
                >
                  {discipline.discipline}
                </button>
              </div>
              ))}
          </div>
        </div>
        <div className="form-group">
          <label>
            <FormattedMessage {...messages.selectQuestion} />
          </label>
          <div className="row">
            <div className="col-xs-1 col-md-4 col-lg-3">
              <button
                className={`btn btn-light-gray btn-block ${this.state.active}`}
                onClick={this.changeActive}
              >
                <FormattedMessage {...messages.typeAutomatic} />
              </button>
            </div>
            <div className="col-xs-1 col-md-4 col-lg-3">
              <button
                className={`btn btn-light-gray btn-block ${this.state.active}`}
                onClick={this.changeActive}
              >
                <FormattedMessage {...messages.typeManual} />
              </button>
            </div>
          </div>
        </div>
        <div className="form-group fg-right">
          <Link className="btn btn-warning" to="#">
            <FormattedMessage {...messages.createAssessment} />
          </Link>
        </div>
      </div>
    </div>
  );
  }
}

The easiest solution to this problem is making the component of the content inside the map and then handling the state of that component there. 解决此问题的最简单方法是将内容的组成部分放入地图中,然后在其中处理该组成部分的状态。 Hence it will maintain individual states. 因此,它将维持各个状态。

It depends what you need. 这取决于您的需求。 You can create separate component for button with state. 您可以为带有状态的按钮创建单独的组件。

You can also keep state of each button in react state as an array, and then you can get the state of each button by index. 您还可以将每个按钮的状态保持为数组的反应状态,然后可以通过索引获取每个按钮的状态。

I'd recommend the first solution, it'd easier to manage such state, but it will be harder to get the state of a specific button from the parent component. 我建议使用第一个解决方案,这样的状态管理起来更容易,但是从父组件中获取特定按钮的状态将更加困难。

Create a separate component for button 为按钮创建一个单独的组件

class MyButton extends Component {
constructor(props){
    super(props);
    this.state = {
        person: this.props.person
    }
}

buttonActiveHandler = () => {
    let oldStatus = this.props.person.status;
    this.props.person.status = (!oldStatus ? 'active': '');
    this.setState({
        person:this.props.person
    });
}
render() {
    return (
        <button className={this.state.person.status} onClick={this.buttonActiveHandler}>{this.state.person.name}</button>
    );
}
}
export default MyButton;

Then import button component. 然后导入按钮组件。 use map function to for your code block 使用map函数到您的代码块

<div className={classes.Box}>
     <h4>Lorem, ipsum.</h4>
    {
       this.props.survey.map((person, i) => {
         return (
            <MyButton key={i} person={person}/>
         )
      })
   }
</div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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