Почему срезы списка React всегда удаляют последнюю строку - PullRequest
0 голосов
/ 29 января 2019

У меня похожий код на 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)

Ответы [ 3 ]

0 голосов
/ 29 января 2019

Вы можете напрямую установить setState в функции удаления.

Я имею в виду;

remove(index) {
  this.setState({
    items: this.state.items.filter((s, sindex) => index !== sindex),
  });
}
0 голосов
/ 31 января 2019

Спасибо всем за отзыв.Это было очень полезно.Я узнал, что вам нужен уникальный ключ, если вы работаете со строками React.Также полезно использовать фильтр вместо «сращивания».Я должен добавить на событие изменения.Я считаю это очень полезным, как только я объединяю один компонент в несколько компонентов.Я обновил решение, чтобы поля ввода не удалялись после удаления одной строки.Я также понял, что в отличие от Angular React связывание выполняется только в одном направлении, и каждое изменение данных должно обновляться через состояние.Вот полное решение: https://jsfiddle.net/wfcev8zb/30/. Особая благодарность пользователю 2340824 за постоянную обратную связь.вот окончательный код:

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"))
0 голосов
/ 29 января 2019

После более тщательной проверки проблема возникает из-за:

      <tr key={record.index}>

Это на самом деле не устанавливается, у вас нет уникального ключа для ваших детей, поэтому React не знает, какойЭти дети были изменены, поэтому, когда вы удаляете одного из них, это немного запутывает.

Вам нужно будет предоставить уникальный ключ для каждой из ваших записей.

Я обновил ваш код ииспользовал new Date().getTime() в качестве быстрого способа получения уникального ключа.

У меня есть рабочий пример здесь https://jsfiddle.net/xk4e1z2s/2/

Вы увидите значение уникального ключа каждой записи, отображаемое по мере ихбудут добавлены, и вы заметите, что удаляется только определенная строка.

Причина, по которой после удаления строки поля ввода пусты, заключается в том, что вам нужно сохранить входные значения вашей записи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...