#reactjs #forms #select #clone
Вопрос:
Этот код добавляет динамические поля ввода с помощью react. Два раскрывающихся списка выбора и один ввод текста. При нажатии на кнопку добавить. та же самая копия этих 3 полей ввода добавляется под старым блоком ввода. Когда я изменяю значение одного выбранного, оно автоматически изменяет другие выбранные входные значения. Например, вы выбираете тип украшения в качестве кольца, а затем отражается другой тип jwellery. Я новичок в 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: "", net_gram: "",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;
Ответ №1:
Вопрос
Основная проблема здесь заключается в том, что у вас есть одно состояние, которое используется для всех входных значений, и, кроме индекса, невозможно отличить один набор входных данных от другого.
Решение
При добавлении новых наборов входных данных в inputList
вы захотите присвоить уникальные id
свойства каждому набору. Это служит нескольким целям:
- Его
id
можно использовать в качестве ключа реакции для каждого сопоставленного набора входных данных. Это помогает при переназначении и согласовании при удалении входных наборов. - Вы можете использовать
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: "",
net_gram: "",
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>
);
}
Комментарии:
1. Большое вам спасибо, сэр, я проверю этот код.
2. Это прекрасно работает, сэр, ваша логика удивительна, большое вам спасибо…!!!!!!!!