如何解决我应该如何管理在 React JS 中动态添加的多个选择字段?
此代码使用 react 添加动态输入字段。 两个选择下拉菜单和一个输入文本。 单击添加按钮时。在旧输入块下方添加了这 3 个输入字段的相同副本。 当我更改选定的值时,它会自动更改其他选择的输入值。例如,您选择珠宝类型作为戒指,则另一种类型的珠宝也得到了体现。我是 React 的初学者。
import React,{useState } from 'react'
import Grid from '@material-ui/core/Grid';
import TextField from '@material-ui/core/TextField';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import InputLabel from '@material-ui/core/InputLabel';
import Select from '@material-ui/core/Select';
import { makeStyles } from "@material-ui/core/styles";
import Button from '@material-ui/core/Button';
const backgroundShape = require('./images/background.svg');
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,backgroundColor: '#064771',overflow: 'hidden',background: `url(${backgroundShape}) repeat`,backgroundSize: 'cover',backgroundPosition: '0 1000px',paddingBottom: 500
},action_btn:{
marginTop:'10px',marginRight: "5px"
},main_grid:{
backgroundColor: '#fff',alignItems: 'center',justifyContent: 'center',margin:'auto',display: 'flex',}
}));
function App() {
const classes = useStyles();
//handle mmultiple input
const [state,setState] = React.useState({
gold_caratage: "",gold_type: ""
});
// handle input change
const handleInputChange = (evt) => {
const value = evt.target.value;
setState({
...state,[evt.target.name]: value
});
};
//clone form logic
const [inputList,setInputList] = useState([{ jwellary_type: "",net_gram: "",caratage:"" }]);
//remove and add btn logic
const handleRemoveClick = index => {
const list = [...inputList];
list.splice(index,1);
setInputList(list);
};
// handle click event of the Add button
const handleAddClick = () => {
setInputList([...inputList,{ jwellary_type: "",caratage:"" }]);
};
return (
<div className={classes.root}>
<typography guttorbuttom align="center">
<h1>React Calc</h1>
</typography>
{inputList.map((x,i) => {
return (
<Grid container className={classes.main_grid} spacing={3}>
<Grid item xs={10} sm={2}>
<FormControl style={{ minWidth:140 }}>
<InputLabel id="demo-simple-select-label">Type Of Jwellary</InputLabel>
<Select
name="gold_type"
value={state.gold_type}
onChange={handleInputChange}
>
<MenuItem value={1}>Ring</MenuItem>
<MenuItem value={2}>Chain</MenuItem>
<MenuItem value={3}>Other</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={10} sm={2}>
<TextField
name="Net Gram"
label="Net Gram"
type="number"
fullwidth
/>
</Grid>
<Grid item xs={10} sm={2}>
<FormControl style={{ minWidth: 120 }}>
<InputLabel id="demo-simple-select-label">Caratage</InputLabel>
<Select
value={state.gold_caratage}
onChange={handleInputChange}
name="gold_caratage"
>
<MenuItem value={1}>22</MenuItem>
<MenuItem value={2}>23</MenuItem>
<MenuItem value={3}>24</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={10} sm={2}>
<Button
variant="contained"
color="secondary"
className={classes.action_btn}
onClick={() => handleRemoveClick(i)}>
Remove
</Button>
<Button
variant="contained"
color="primary"
className={classes.action_btn}
onClick={handleAddClick}>
Add
</Button>
</Grid>
</Grid>
);
})}
</div>
)
}
export default App;
解决方法
问题
这里的主要问题是您有一个用于所有输入值的状态,除了索引之外,无法区分一组输入和下一组输入。
解决方案
向 inputList
添加新输入集时,您需要为每个集分配唯一的 id
属性。这有几个目的:
-
id
可用作每个映射输入集的 React 键。这有助于在删除输入集时重新呈现和协调。 - 您可以使用
id
更新和删除状态。
不需要单独输入 state
状态,inputList
状态具有所有必需的数据。
import { v4 as uuidV4 } from 'uuid';
export default function App() {
const classes = useStyles();
//clone form logic
const [inputList,setInputList] = useState([
{
id: uuidV4(),// <-- provide id
jwellary_type: "",net_gram: "",caratage: ""
}
]);
// handle input change
const handleInputChange = (id) => (evt) => {
const { value } = evt.target;
setInputList((list) =>
list.map((el) => // <-- shallow copy array
el.id === id // <-- match by id
? {
...el,// <-- shallow copy element
[evt.target.name]: value // <-- update key/value
}
: el // <-- or return current element
)
);
};
//remove and add btn logic
const handleRemoveClick = (id) => {
// <-- shallow copy array and remove elements with mismatch id
setInputList((list) => list.filter((el) => el.id !== id));
};
// handle click event of the Add button
const handleAddClick = () => {
setInputList([
...inputList,{
id: uuidV4(),// <-- provide id
jwellary_type: "",caratage: ""
}
]);
};
return (
<div className={classes.root}>
<typography guttorbuttom align="center">
<h1>React Calc</h1>
</typography>
{inputList.map((x,i) => {
return (
<Grid
key={x.id} // <-- provide id as React key
container
className={classes.main_grid}
spacing={3}
>
<Grid item xs={10} sm={2}>
<FormControl style={{ minWidth: 140 }}>
<InputLabel id="demo-simple-select-label">
Type Of Jwellary
</InputLabel>
<Select
name="jwellary_type" // <-- name to match property
value={x.jwellary_type} // <-- current property
onChange={handleInputChange(x.id)} // <-- pass id
>
<MenuItem value={1}>Ring</MenuItem>
<MenuItem value={2}>Chain</MenuItem>
<MenuItem value={3}>Other</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={10} sm={2}>
<TextField
name="Net Gram"
label="Net Gram"
type="number"
fullwidth
/>
</Grid>
<Grid item xs={10} sm={2}>
<FormControl style={{ minWidth: 120 }}>
<InputLabel id="demo-simple-select-label">Caratage</InputLabel>
<Select
value={x.caratage} // <-- current property
onChange={handleInputChange(x.id)} // <-- pass id
name="caratage" // <-- name to match property
>
<MenuItem value={1}>22</MenuItem>
<MenuItem value={2}>23</MenuItem>
<MenuItem value={3}>24</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={10} sm={2}>
<Button
variant="contained"
color="secondary"
className={classes.action_btn}
onClick={() => handleRemoveClick(x.id)} // <-- pass id
>
Remove
</Button>
<Button
variant="contained"
color="primary"
className={classes.action_btn}
onClick={handleAddClick}
>
Add
</Button>
</Grid>
</Grid>
);
})}
</div>
);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。