reactjs - 更改输入值后,表 1 的值需要保持不变
问题描述
我是 React 的新手,我试图通过单击按钮添加表格行。问题是输入标签中的值被添加到表中。但是在添加另一行时值需要保持不变。一旦我更改输入中的值,相应的表行值也会更改。我希望表值是永久的并且根据输入标签中的输入变化而有所不同。
这是我的 KPI 详细信息代码:
export class KPIDetails extends Component {
state = {
rows: [],
idx: [1]
};
continue = e => {
e.preventDefault();
this.props.nextStep();
};
handleChangeRows = idx => e => {
const { name, value } = e.target;
const rows = [...this.state.rows];
rows[idx] = {
[name]: value
};
this.setState({
rows
});
};
//2
handleAddRow = () => {
const item = {
KPI_Before: "",
UOM_Before: "",
Base_Before: "",
Target_Before: "",
dateTime: ""
};
this.setState({
rows: [...this.state.rows, item]
});
};
//3
handleRemoveRow = () => {
this.setState({
rows: this.state.rows.slice(0, -1)
});
};
setDate = dateTime => this.setState({ dateTime });
render() {
const { values, handleChange } = this.props;
const {
values: {
Title,
Details,
What,
Why,
How,
Status,
Cost,
Benefits,
Kpi_Before,
Kpi_After,
UOM_Before,
Base_Before,
Target_Before,
Time,
dateTime
}
} = this.props;
return (
<MuiThemeProvider theme={theme}>
<React.Fragment>
<div className={useStyles.root}>
<AppBar position="static">
<Toolbar>
<Typography
gutterBottom
align="center"
style={{ width: "100%", alignItems: "center" }}
>
KPI Before Implementation
</Typography>
</Toolbar>
</AppBar>
</div>
<br />
<br />
<Grid container>
<Grid item xs={6}>
<TextField
label="KPI"
id="Kpi_Before"
variant="outlined"
size="small"
placeholder="Enter the KPI"
onChange={handleChange("Kpi_Before")}
defaultValue={values.Kpi_Before}
style={{ width: "80%" }}
/>
</Grid>
<Grid item xs={6}>
<FormControl style={{ width: "80%" }} size="small">
<InputLabel
htmlFor="UOM_Before"
style={{
marginLeft: 10,
top: "50%",
transform: "translate(0,-50%"
}}
>
UOM
</InputLabel>
<Select
labelId="UOM_Before"
name="name"
onChange={handleChange("UOM_Before")}
defaultValue={values.UOM_Before}
variant="outlined"
inputProps={{
id: "UOM_Before"
}}
>
<MenuItem value="Nos">Nos</MenuItem>
<MenuItem value="Percentage">Percentage</MenuItem>
<MenuItem value="Metric">Metric</MenuItem>
</Select>
</FormControl>
</Grid>
</Grid>
<br />
<br />
<br />
<br />
<Grid container>
<Grid item xs={6}>
<TextField
label="Base Level"
variant="outlined"
size="small"
placeholder="Enter the Base Level"
onChange={handleChange("Base_Before")}
style={{ width: "80%" }}
/>
</Grid>
<Grid item xs={6}>
<TextField
label="Target Level"
variant="outlined"
size="small"
placeholder="Enter the Target Level"
onChange={handleChange("Target_Before")}
defaultValue={values.Target_Before}
style={{ width: "80%" }}
/>
</Grid>
</Grid>
<br />
<br />
<br />
<br />
<Grid container>
<Grid item xs={6} direction="row" alignItems="center">
<TextField
id="date"
label="Target Date"
type="date"
variant="outlined"
size="small"
defaultValue="2017-05-24"
onChange={handleChange("dateTime")}
style={{ width: "67%" }}
InputLabelProps={{
shrink: true
}}
/>
<Button
variant="outlined"
color="primary"
onClick={this.handleAddRow}
size="small"
style={styles.button}
>
+
</Button>
</Grid>
<Grid item xs={6}>
...
</Grid>
</Grid>
<Grid container>
<Grid item xs={6} direction="row" alignItems="center">
<table
className="table table-bordered table-hover"
id="tab_logic"
>
<thead>
<tr>
<th className="text-center"> # </th>
<th className="text-center"> KPI </th>
<th className="text-center"> UOM </th>
<th className="text-center"> Base </th>
<th className="text-center"> Target </th>
<th className="text-center"> Target Date </th>
</tr>
</thead>
<tbody>
{this.state.rows.map((item, idx) => (
<tr id="addr1" key={idx}>
<td>{idx}</td>
<td>
<input
type="text"
name="Kpi_Before"
value={Kpi_Before}
onChange={this.handleChangeRows(idx)}
className="form-control"
/>
</td>
<td>
<input
type="text"
name="UOM_Before"
value={UOM_Before}
onChange={this.handleChangeRows(idx)}
className="form-control"
/>
</td>
<td>
<input
type="text"
name="Base_Before"
value={Base_Before}
onChange={this.handleChangeRows(idx)}
className="form-control"
/>
</td>
<td>
<input
type="text"
name="Target_Before"
value={Target_Before}
onChange={this.handleChangeRows(idx)}
className="form-control"
/>
</td>
<td>
<input
type="text"
name="Target_Before"
value={dateTime}
onChange={this.handleChangeRows(idx)}
className="form-control"
/>
</td>
</tr>
))}
</tbody>
</table>
<button
onClick={this.handleRemoveRow}
className="pull-right btn btn-default"
>
Delete Row
</button>
</Grid>
</Grid>
</React.Fragment>
</MuiThemeProvider>
);
}
}
const theme = createMuiTheme({
palette: {
primary: blue,
secondary: purple
},
status: {
danger: "orange"
}
});
const styles = {
button: {
margin: 5,
verticalAlign: "bottom"
}
};
export default KPIDetails;
这是我的用户表单代码:
export class UserForm extends Component {
state = {
step: 1,
Title: "",
Details: "",
What: "",
Why: "",
How: "",
Status: "",
Cost: "",
Benefits: "",
Kpi_Before: "",
Kpi_After: "",
Time: "",
UOM_Before: "",
Base_Before: "",
Target_Before: "",
dateTime: null,
rows: []
};
//1
handleChangeRows = idx => e => {
const { Kpi_Before, value } = e.target;
const rows = [...this.state.rows];
rows[idx] = {
[Kpi_Before]: value
};
this.setState({
rows
});
};
//2
handleAddRow = () => {
const item = {
KPI_Before: "",
UOM_Before: "",
Base_Before: "",
Target_Before: "",
dateTime: ""
};
this.setState({
rows: [...this.state.rows, item]
});
};
//3
handleRemoveRow = () => {
this.setState({
rows: this.state.rows.slice(0, -1)
});
};
//Proceed to next step
nextStep = () => {
const { step } = this.state;
this.setState({
step: step + 1
});
};
//Go back to previous step
prevStep = () => {
const { step } = this.state;
this.setState({
step: step - 1
});
};
//Handle fields change
handleChange = input => e => {
this.setState({ [input]: e.target.value });
};
render() {
const { step } = this.state;
const {
Title,
Details,
What,
Why,
How,
Status,
Cost,
Benefits,
Kpi_Before,
Kpi_After,
Time,
UOM_Before,
Base_Before,
Target_Before,
dateTime,
rows
} = this.state;
const values = {
Title,
Details,
What,
Why,
How,
Status,
Cost,
Benefits,
Kpi_Before,
Kpi_After,
Time,
UOM_Before,
Base_Before,
Target_Before,
dateTime,
rows
};
switch (step) {
case 1:
return (
<FormUserDetails
nextStep={this.nextStep}
handleChange={this.handleChange}
values={values}
/>
);
case 2:
return (
<KPIDetails
handleChange={this.handleChange}
values={values}
nextStep={this.nextStep}
handleChangeRows={this.handleChangeRows}
handleAddRow={this.handleAddRow}
handleRemoveRow={this.handleRemoveRow}
/>
);
case 3:
return (
<Confirm
nextStep={this.nextStep}
prevStep={this.prevStep}
values={values}
/>
);
case 4:
return <Success />;
}
}
}
export default UserForm;
请告诉我如何实现这一目标?
解决方案
我是新手,所以我对这些概念并不完全清楚。
使用 JavaScript/jQuery 从其输入元素中获取值的传统 HTML 表单是具有不受控制组件的典型表单。没有显式使用状态变量,也没有实现任何事件处理程序来更新输入值。因此,在这种情况下,将 onChange() 插入不受控制的组件将是不必要的。它们的值就是我们输入的内容。在 react 提交表单时,通过附加 ref 的 current 属性实现对元素的引用。因此,用户输入的值可以通过 current.value 获得。
在 React 渲染的生命周期中,表单元素中的值属性会覆盖 DOM 中的值。为了处理这种情况,React 提出了 defaultValue 属性,它指定了初始值,但不控制随后的更新。
React 将输入视为受控(与 prop/state 绑定的值)或不受控(不绑定值)。
当我像这样在表单中使用值时:
<td>
<input
type="text"
name="Base_Before"
value={Base_Before}
onChange={this.handleChangeRows(idx)}
className="form-control"
/>
</td>
它的值会在更改输入字段时自动更改。所以每次我更新并向表中添加行时,它的值总是会反映输入字段中的值。Defaultvalue 不会在更新输入值时更新状态,因此在一行中输入的值将保持永久不变,并且不会随着输入字段中的更改而更改。
再次,我是新来的反应,这是我所理解的,如果我错了,请纠正我,希望这会有所帮助
推荐阅读
- javascript - 在尝试获取所需的对象格式时获取空数据
- javascript - 如何将多个角色设置为 mainRole
- python - Numpy.Append():ValueError:无法将输入数组从形状(4)广播到形状(3)
- firebase - 'java.lang.String com.google.firebase.auth.FirebaseUser.getUid()' 在空对象引用 androidx
- servicenow - 无法查看附带 ServiceNow 表记录的 PDF
- java - 如何在 Intellij Idea 中找到包
- angular - 从模板中的 *ngFor 调用时,Angular 10 服务未定义
- xmlhttprequest - Internet Explorer 11 自动重试失败的 ajax 请求
- vb.net - VB.Net:定位上下文菜单
- sql - PostgreSQL 索引不用于查询