Próbuję usunąć wiele div
, które zostały wygenerowane za pomocą przycisku dodawania. Mam problem ze zrozumieniem, w jaki sposób mogę wysłać identyfikator nadrzędnego elementu div do metody usuwania przekazanej z podrzędnego elementu div. Ponadto, jeśli mogę zapisać identyfikator div w stanie, aby wykonać proces usuwania. Mój kod jest następujący. Doceniam twoje uwagi i sugestie.
constructor(props) {
super(props);
this.state = {
names: [],
inputValue: '',
id: [],
count: 1,
hostname: '',
devname: '',
sID: '',
}
this.addRow = this.addRow.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.deleteRow = this.deleteRow.bind(this)
}
addRow() {
this.setState({ count: this.state.count + 1 })
console.log(`Increase count: ${this.state.count}`)
};
renderDivs() {
let count = this.state.count, uiItems = [];
var { names } = this.state;
let options2 = names.map(name2 => {
return { value: name2.name, label: name2.name };
})
while (count--)
uiItems.push(
<div className="newHost" id="dynamic">
<div className="hostInput">
<input type="text" placeholder="Enter Name"
onChange={this.handleChangeHN.bind(this)}
/>
</div>
<div className="hostInput">
<Select
placeholder="Pick Dev Name..."
styles={colourStyles}
options={options2}
onChange={this.handleChangeDN}
/>
</div>
<div className="hostInput">
<button className="btn btn-danger" type="button" onClick={this.deleteRow}>Remove</button>
</div>
</div>
)
return uiItems;
}
deleteRow(currentID) {
// const changedID = this.state.id.filter(i => i.id !== currentID)
// this.setState({changedID});
// console.log(`Clicked: ${currentID}`);
// this.setState({ count: this.state.count - 1 })
console.log("delete");
};
render() {
let options = sData.map(name => {
return { value: name.name, label: name.name };
})
return (
<div className="wrapper">
<div className="form-wrapper">
<Toolbar />
<form className="form" onSubmit={this.handleSubmit}>
<label className="label1">Select SaleID</label> <hr />
<div>
<Select
value={this.state.inputValue}
onChange={this.handleChange}
options={options}
/>
<div style={{ color: 'red', marginTop: '5px' }}>
{this.state.validationError}
</div>
<br />
</div>
<label className="label1">Create New Sale</label>
<hr />
<div className="addButton">
<button type="button" onClick={this.addRow}>Add</button>
{this.renderDivs()}
</div>
<hr />
<div className="submitButton">
<button type="submit">Submit</button>
</div>
</form>
</div>
</div>
)
}
Z góry dziękuję!
1 odpowiedź
Programując w React należy najpierw zapomnieć o identyfikatorach html. Kiedy dodajesz lub usuwasz wiersz, masz do czynienia z danymi, a nie elementami html. Twój przykład nie zawiera wszystkich komponentów kodu i brakuje w nim funkcji handleChangeHN
i handleChangeHN
, więc podam tylko przykład odpowiednich części kodu:
constructor(props) {
super(props);
this.state = {
rows: [],
}
//...
}
addRow() {
const newRow = {
name: '',
devName: '',
};
this.setState({ rows: [...this.state.rows, newRow] })
};
deleteRow(position) {
this.setState({ rows: this.state.rows.filter((_, i) => i !== position) })
}
renderDivs() {
const { rows } = this.state;
const options2 = rows.map(name2 => {
return { value: name2.name, label: name2.name };
});
return rows.map( (row, i) => (
<div className="newHost" key="_{i}">
<div className="hostInput">
<input type="text" placeholder="Enter Name"
value={row.name}
onChange={this.handleChangeHN.bind(this)}
/>
</div>
<div className="hostInput">
<Select
placeholder="Pick Dev Name..."
styles={colourStyles}
options={options2}
value={row.devName}
onChange={this.handleChangeDN}
/>
</div>
<div className="hostInput">
<button className="btn btn-danger" type="button" onClick={() => this.deleteRow(i)}>Remove</button>
</div>
</div>
));
}
PS: używanie iteratora jako klucza key="_{i}"
nie jest dobrą praktyką, ale ponieważ masz tylko pola wejściowe użytkownika, nie można ich używać jako identyfikatora. Inną opcją byłoby użycie generatora losowych identyfikatorów lub po prostu przechowywanie liczby kliknięć w stanie i używanie go jako identyfikatora podczas dodawania nowych wierszy.
PPS: na marginesie, nie należy wiązać komponentów obsługujących funkcje podczas renderowania tak, jak to robisz onChange={this.handleChangeHN.bind(this)}
. Spowoduje to utworzenie nowej funkcji za każdym razem, gdy komponent jest renderowany, więc jest to powolny wyciek pamięci. Powiąż funkcje tak jak w konstruktorze lub po prostu użyj składni ecmascript 6 handleChangeHN = () => {...
.
deleteRow
powinna byćdeleteRow(event)
i wewnątrz tej funkcji możesz uzyskać dostęp do identyfikatora rodzica:event.target.parentNode.id
.sData
?