我无法正确实现这种简单的添加和删除输入,当我有3个字段时,我填写了所有输入,单击了第二项上的Delete,我想看到的是值1和2,但是没有?
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
rows: [
{
id: 1
}
]
};
}
addRow = () => {
this.setState(
{
rows: [...this.state.rows, { id: this.state.rows.length + 1 }]
},
() => console.log(this.state.rows)
);
};
deleteRow = id => {
console.log(id);
const { rows } = this.state;
this.setState({
rows: rows.filter(row => row.id !== id)
});
};
render() {
const { rows } = this.state;
return (
<div>
{rows.map(o => (
<div>
<input key={o.id} id={o.id} placeholder={"text"} type="text" />
<div
style={{ display: "inline-block" }}
onClick={e => this.deleteRow(o.id)}
>
x
</div>
</div>
))}
<button onClick={this.addRow}>add</button>
</div>
);
}
}
演示:image
答案 0 :(得分:0)
需要对输入的值进行控制,以使其保持不变。如果不加以控制,则值将一直保留到该输入生命周期的尽头,并且由于更改了位置而在渲染中重新创建了它们,因此它们会丢失键入的值。
这应该有效:
import React from "react";
import ReactDOM from "react-dom";
import uuid from "uuid";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentId: 1,
rows: [
{
id: uuid(),
value: '',
}
]
};
}
addRow = () => {
this.setState(
{
rows: [...this.state.rows, { id: uuid(), value: '' }]
},
() => console.log(this.state.rows)
);
};
deleteRow = id => {
console.log(id);
const { rows } = this.state;
this.setState({
rows: rows.filter(row => row.id !== id)
});
};
handleChangeRow = (id) => ({target: {value}}) => this.setState({rows: this.state.rows.map(row => row.id === id ? {...row, value} : row)})
render() {
const { rows } = this.state;
return (
<div>
{rows.map(o => (
<div>
<input value={o.value} key={o.id} id={o.id} placeholder={"text"} type="text"
onChange={this.handleChangeRow(o.id)}/>
<div
style={{ display: "inline-block" }}
onClick={e => this.deleteRow(o.id)}
>
x
</div>
</div>
))}
<button onClick={this.addRow}>add</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
https://codesandbox.io/s/p785wv1z7m
编辑:更改为ID以使用uuid来保证唯一性,但是为了公平起见,您通常不需要为状态中的组件数组分配ID,如另一个答案所述。您可以只使用索引,或者如果组件数据中已经具有固有ID,那也可以使用。
答案 1 :(得分:0)
确定有1个错误是在您将项目ID设置为长度时。因此,如果您添加2,请删除第一个,然后添加一个,您将拥有两个具有相同ID的
。[{id: 1}]
// Push one
[{id: 1}, {id: 2}]
// Delete value of 1
[{id: 2}]
// Push one
[{id: 2}, {id: 2}] // wooops!
在这种情况下,我会根据数组的索引进行添加/删除,以解决问题。
答案 2 :(得分:0)
除了在状态更改中未保存值外,还为输入分配了不正确的ID,这导致多个ID具有相同的ID并被一起删除。这是一个简单易读的修复程序,它带有saveValue
方法,用于在每次更改时保存输入值:
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentId: 1,
rows: [
{
id: 1,
value: ''
}
]
};
}
addRow = () => {
this.setState(
{
currentId: this.state.currentId + 1,
rows: [...this.state.rows, { id: this.state.currentId + 1, value: '' }]
},
console.log(this.state.rows)
);
};
deleteRow = id => {
console.log(id);
let rows = this.state.rows;
this.setState({
rows: rows.filter(row => row.id !== id)
});
};
saveValue = (e, id) => {
let rows = this.state.rows;
rows[id - 1].value = e.target.value;
this.setState({ rows: rows });
}
render() {
const { rows } = this.state;
return (
<div>
{rows.map(o => (
<div key={o.id}>
<input id={o.id} value={o.value} placeholder={"text"} type="text" onChange={e => this.saveValue(e, o.id)}/>
<div
style={{ display: "inline-block" }}
onClick={() => this.deleteRow(o.id)}
>
x
</div>
</div>
))}
<button onClick={this.addRow}>add</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
https://codesandbox.io/s/qqvvq27k36
还要注意,当您使用map
添加元素时,map
中最顶层的元素(在这种情况下为div
)需要具有key
属性,而不是输入元素。那并没有破坏任何东西,但是遵循该规则是一种很好的做法。
答案 3 :(得分:0)
与@Bernardo Siqueira的答案非常相似,但是:
y1
用作name
id
数组的当前结构/值工作示例:https://codesandbox.io/s/qm96vv8z9
index.js
this.state.Fields
FieldInput.js
import map from "lodash/map";
import filter from "lodash/filter";
import React, { Component } from "react";
import { render } from "react-dom";
import FieldInput from "./FieldInput";
import "uikit/dist/css/uikit.min.css";
import "./styles.css";
class App extends Component {
state = {
fieldsCount: 1,
Fields: [
{
name: "Field0",
value: ""
}
]
};
handleChange = name => ({ target: { value } }) => {
this.setState(prevState => ({
Fields: map(
this.state.Fields,
field => (field.name === name ? { ...field, value } : field)
)
}));
};
showFieldValues = fields => {
return map(fields, ({ value }) => value);
};
handleSubmit = e => {
e.preventDefault();
alert(`Field value(s): ${this.showFieldValues(this.state.Fields)}`);
};
addField = () => {
this.setState(prevState => ({
Fields: [
...this.state.Fields,
{
name: `Field${this.state.fieldsCount}`,
value: ""
}
],
fieldsCount: this.state.fieldsCount + 1
}));
};
deleteField = name => {
this.setState(prevState => ({
Fields: filter(this.state.Fields, field => field.name !== name)
}));
};
render = () => (
<form onSubmit={this.handleSubmit} style={{ textAlign: "center" }}>
<h1>Dynamic Field Creation</h1>
<FieldInput
{...this.state}
deleteField={this.deleteField}
handleChange={this.handleChange}
/>
<button
type="button"
style={{ marginRight: 20 }}
className="uk-button uk-button-primary"
onClick={this.addField}
>
Add Field
</button>
<button type="submit" className="uk-button uk-button-secondary">
Submit
</button>
<pre style={{ textAlign: "left", height: 300, scrollY: "auto" }}>
<code>{JSON.stringify(this.state.Fields, null, 4)}</code>
</pre>
</form>
);
}
render(<App />, document.getElementById("root"));