【问题标题】:Why React list slice always delete the last row为什么 React 列表切片总是删除最后一行
【发布时间】:2019-01-29 20:31:15
【问题描述】:

我在 Angular 中有类似的代码,而且效果很好。我试图将代码转换为 React 版本。它工作得很好,除非我尝试删除一行。每次删除单击都会删除最后一行。我的期望是删除我单击“删除”按钮的行。我正在传递需要删除的索引项。我提供了下面的示例,您也可以在这里尝试...https://jsfiddle.net/w6cy0bx1/11/

class MineCts extends React.Component{
constructor(props){
super(props);
this.state = {
items:[]
};
}

render(){
return(
<div>
  <div><button onClick={(event)=>this.add(event)} >Add</button></div>
  <div>
    This is sample:
    {this.state.items.map((record, index)=>{
    return(
    <table>
      <tr key={index}>
        <td> <input id="Name" value={record.Name} onChange={this.onDataChange}/> </td>
        <td> <input id="Counter" value={record.Counter} onChange={this.onDataChange} /> </td>
        <td><button onClick={(event)=>this.remove(event, record, index)} >Remove</button></td>
      </tr>
    </table>
    )
    })}

  </div>
</div>
)
}

onDataChange(e)
{
console.log(e.target.id)
this.setState({[e.target.id]:e.target.value})
}

add(e){
let rows = this.state.items;
rows.push({});
this.setState({items:rows})
}

remove(e, record, index){
console.log(record)
console.log(index)
let rows = this.state.items;
rows.splice(index, 1);
this.setState({items:rows})
}

}



ReactDOM.render(<MineCts />, mountNode)

【问题讨论】:

    标签: asp.net-mvc reactjs


    【解决方案1】:

    经过仔细检查,问题是由于:

          <tr key={record.index}>
    

    这实际上并没有被设置,你的孩子没有唯一的密钥,所以 React 不知道这些孩子中的哪一个被修改了,所以当你删除其中一个时,它有点困惑。

    您需要为每条记录提供唯一的密钥。

    我更新了您的代码并使用new Date().getTime() 作为获取唯一密钥的快速方法。

    我在https://jsfiddle.net/xk4e1z2s/2/ 有一个工作示例

    您将看到每条记录的唯一键的值在添加时显示,并且您会注意到只有特定行被删除。

    删除一行后输入字段为空的原因是您需要保存记录的输入值。

    【讨论】:

    • 我试过你的答案不起作用。我还使用了这样的新数组 let rows = [...this.state.items];还是不行。它总是删除最后一行。您可以在这里尝试您的解决方案jsfiddle.net/w6cy0bx1/11
    • 我的回答不正确,我深表歉意。我已经确定了这个问题,现在在jsfiddle.net/xk4e1z2s/2 提供了一个可行的解决方案
    • 感谢您的反馈。你是对的,它需要密钥,但如果没有正确挂钩更改事件,它仍然无法正常工作。我更新了解决方案,以便在您输入记录后输入字段不会被清除。我还意识到,与 Angular React 不同,只有一种方式绑定,并且每次数据更改都必须通过状态进行更新。这是完整的解决方案:jsfiddle.net/wfcev8zb/30
    【解决方案2】:

    您可以直接在您的删除功能上执行 setState。

    我的意思是;

    remove(index) {
      this.setState({
        items: this.state.items.filter((s, sindex) => index !== sindex),
      });
    }
    

    【讨论】:

    • 感谢您的反馈,但它没有删除正确的索引行。它总是删除最后一行。你可以在这里试试你的答案jsfiddle.net/w6cy0bx1/11
    【解决方案3】:

    感谢大家的反馈。这很有帮助。我了解到,如果您使用 React 行,则需要有一个唯一的键。使用过滤器代替“拼接”也很有帮助。我必须添加更改事件。当我将一个组件组合成多个组件时,我发现它非常有用。我更新了解决方案,以便在删除单行后不会清除输入字段。我还意识到,与 Angular React 不同的是,只有一种方式绑定,并且每次数据更改都必须通过状态进行更新。这是完整的解决方案:https://jsfiddle.net/wfcev8zb/30/。特别感谢 user2340824 的持续反馈。 这是最终代码:

    class MineCts extends React.Component{
    constructor(props){
    super(props);
    this.state = {
    items:[]
    };
    
    this.add = this.add.bind(this);
    this.onDataChange = this.onDataChange.bind(this);
    this.remove = this.remove.bind(this);
    }
    
    render(){
    return(
    <div>
      <div><button onClick={this.add} >Add</button></div>
      <div>
        This is sample:
    
    {this.state.items.map((record, index)=>{
        return(
        <DetailTable record ={record} callOnChangeFunc={this.onDataChange} callOnRemoveFunc={this.remove} />
      );
        })}
    
          </div>
    </div>
    )
    }
    
    onDataChange(e, record)
    {
    e.preventDefault();
    let rows = [...this.state.items];
    record[e.target.id]=e.target.value;
    rows[record.Id] = record;
    this.setState({items:rows})
    }
    
    add(e){
    let rows = [...this.state.items];
    rows.push({Id: new Date().getTime(), Name:null, Counter:null});
    this.setState({items:rows})
    }
    
    remove(e, record){
    e.preventDefault();
    let rows = [...this.state.items.filter(x=>x.Id!==record.Id)];
    this.setState({items:rows})
    }
    
    }
    
    class DetailTable extends React.Component{
    constructor(props){
    super();
    this.callOnChange = this.callOnChange.bind(this);
    this.callOnRemove = this.callOnRemove.bind(this);
    }
    callOnChange(e){
    this.props.callOnChangeFunc(e, this.props.record);
    }
    callOnRemove(e){
    this.props.callOnRemoveFunc(e, this.props.record);
    }
    
    render(){
    return (
    <div>
      <table>  
          <tr key={this.props.record.Id} >
            {this.props.record.Id}
            <td> 
            <input id="Name" value={this.props.record.Name} onChange={this.callOnChange} /> </td>
            <td> 
            <input id="Counter" value={this.props.record.Counter}  onChange={this.callOnChange}  /> </td>
            <td><button onClick={this.callOnRemove} >Remove</button></td>
          </tr>
       </table>
    </div>     
    );
    }
    }
    
    ReactDOM.render(<MineCts />, document.querySelector("#app"))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-09
      • 2013-08-20
      • 1970-01-01
      • 1970-01-01
      • 2017-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多