如何更改特定于项目的状态?

时间:2018-01-29 20:54:03

标签: javascript reactjs react-native state

我目前正在创建一个包含每行中客户信息的表。最后一列标题为“删除”,单击时应触发删除行。每行都有一个显示“是”的按钮,当您单击它时,它将变为“确认”,最后一次点击将触发删除。目前我设置它的方式,它按我想要的方式工作但是当你点击其中一个按钮时,所有按钮都执行相同的操作;因此,在这种情况下,如果单击一个按钮,则所有这些按钮都将更改为“确认”,而不是仅更改该特定行的按钮。

我知道这是因为我没有唯一的标识符/索引,所以它改变了每个按钮的状态。我目前正在传递索引,但我不确定如何使用它。我不确定如何完成我需要的东西,并且不喜欢任何关于如何改变特定行的状态的建议。需要有button colorbutton textfirst_clicksecond_click的初始状态,然后当客户点击该行的按钮时,状态将会发生变化。以下是需要更改为特定每行的整体理想行为的代码片段。

设置初始状态:

constructor(props) {
    super(props);
    this.state = {
        buttonColor: "#FD8F83", 
        buttonText: "Yes", 
        first_click: false, 
        second_click: false,
    };
  }

点击时设置状态:

  handleClick(i) {
    if (this.state.first_click === false) {
      console.log("first click");
      this.setState({
        buttonColor: "#A4D87C",
        buttonText: "Confirm?",
        first_click: true
      });
    } else if (this.state.first_click === true && this.state.second_click === false) {
      console.log("second click");
      this.setState({
        second_click: true,
      });
    } else {
      console.log("third or more click");
    }
    }

App的渲染功能返回的部分内容:

<tbody>
          {this.props.initialCustomers.map((customer, index) => {
              return (
                <Customer 
                    name={customer.customer} 
                    fb_un={customer.fbun} 
                    em_un={customer.emun} 
                    key={customer._id}
                    id={customer._id}
                    handleClick={function() {this.handleClick(index)}.bind(this)}
                    buttonColor={this.state.buttonColor}
                    buttonText={this.state.buttonText}
                    first_click={this.state.first_click}
                    second_click={this.state.second_click}
                />
              );
            })
          }
</tbody>

如果这很明显我道歉,我是React的新手。

在我在Team Treehouse上执行的单独项目中,我们使用this.state.players[index].score += delta;this.setState(this.state);设置了州。但是,当我在这个项目中使用类似的方法(例如,this.state.buttonColor = "A4D87C")时,我得到以下错误。我也尝试了许多其他的在线工作,无法让它工作,如果它有用,我可以发布我已经完成的工作,但我不确定它是否有用。

  

不要直接改变状态。使用setState()   反应/无直接突变状态

任何帮助将不胜感激!如果我能提供任何其他信息,请告诉我。谢谢!

4 个答案:

答案 0 :(得分:0)

我没有看到你正在运行的玩家循环,但它可能会被解决...

替换:

this.state.players[index].score += delta;
this.setState(this.state);

使用:

let { players } = this.state;
players[index].score += delta;
this.setState({ players });

答案 1 :(得分:0)

使用lodash函数获得更好的空代码。 如果使用immutableJs管理状态会更好。

这是达到你想要的一种方式。

import cloneDeep from 'lodash/cloneDeep';

// Cloning players.
const players = cloneDeep(this.state.players);

// Updating its values.
players[index].score += delta;

// setting the state with the new cloned players
this.setState({
    players
})

答案 2 :(得分:0)

你应该创建一个组件ButtonRow。 每一行,都有自己的内部状态获得自己的按钮。

class ButtonRow extends React.Component {
    constructor() {
        super()
        this.state = {
            state: 0; // 0: display 'Yes'; 1: display Confirm
        }

    }

    removeRow = () => {
        if(this.state.state === 1) {
            this.props.deleteRow(this.props.index);
        }
        else {
            const currentState = this.state.state;
            this.setState({state: currentState + 1});
        }
    };



    render() {
        const differentDisplay = ['Yes','Confirm'];
        <button onClick={ () => this.props.removeRow() }>
            {differentDisplay[this.state.state]}
        </button>

    }

};

在组件Customer中调用ButtonComponent并提供remove函数和与该行对应的数组的索引。

答案 3 :(得分:0)

根据@Leeroy_Wonkledge的评论,我能够让这个工作。下面是我的ButtonRow组件的样子。

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class ButtonRow extends Component {
    constructor(props) {
        super(props);
        this.state = {
            buttonColor: "#FD8F83",
            button: 0 
        };
    }

    deleteRow = (i) => {
        console.log("delete row", i);
    }

    removeRow = (i) => {
        if(this.state.button === 1) {
            const currentState = this.state.button;
            this.setState({
                button: currentState + 1
            });
            this.deleteRow(this.props.index);
        }
        else if (this.state.button === 0) {
            const currentState = this.state.button;
            this.setState({
                button: currentState + 1,
                buttonColor: "#A4D87C",
            });
        }
    };

    render() {
        const differentDisplay = ['Yes','Confirm'];
        return (
            <button 
            style={{backgroundColor: this.state.buttonColor}} 
            onClick={ () => this.removeRow() }>
                {differentDisplay[this.state.button]}
            </button>
        );
    }
}

ButtonRow.propTypes = {
    index: PropTypes.number.isRequired
};

export default ButtonRow;