代码之家  ›  专栏  ›  技术社区  ›  Dallas Huggins

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

  •  0
  • Dallas Huggins  · 技术社区  · 6 年前

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

    我知道这是因为我没有唯一的标识符/索引,所以它会更改每个按钮的状态。我目前正在传递索引,但我不确定如何使用它。我不知道如何实现我所需要的,并希望得到关于如何更改特定行状态的任何建议。需要为 button color , button text , first_click second_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");
        }
        }
    

    应用程序渲染函数返回的一部分:

    <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>
    

    我很抱歉,如果这是显而易见的,我是新手。

    在我在Team Treehouse上做的另一个项目中,我们将状态设置为 this.state.players[index].score += delta; this.setState(this.state); . 然而,当我在这个项目上使用类似的方法时(例如, this.state.buttonColor = "A4D87C" )我得到以下错误。我也在网上尝试了很多其他的东西,但都没能成功。如果有帮助的话,我可以把我所做的张贴出来,但我不确定如果不成功会有什么影响。

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

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

    4 回复  |  直到 6 年前
        1
  •  0
  •   Leeroy_Wonkledge    6 年前

    您应该创建一个组件按钮箭头。 每行,都有自己的按钮和自己的内部状态。

    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>
    
        }
    
    };
    

    在组件客户内部调用ButtonComponent,并提供移除函数和对应于行的数组索引。

        2
  •  0
  •   ReyHaynes    6 年前

    我看不到你正在运行的球员循环,但这可能会被修复。。。

    替换:

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

    使用:

    let { players } = this.state;
    players[index].score += delta;
    this.setState({ players });
    
        3
  •  0
  •   Tirth Shah    6 年前

    使用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
    })
    
        4
  •  0
  •   Dallas Huggins    6 年前

    根据@Leeroy\u 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;