Как я должен управлять несколькими полями выбора, динамически добавляемыми в React JS?

#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 свойства каждому набору. Это служит нескольким целям:

  1. Его id можно использовать в качестве ключа реакции для каждого сопоставленного набора входных данных. Это помогает при переназначении и согласовании при удалении входных наборов.
  2. Вы можете использовать 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>
  );
}
 

Отредактируйте, как-я-должен-управлять-несколькими-полями-выбора-динамически-добавляемыми-в-реакции-js

Комментарии:

1. Большое вам спасибо, сэр, я проверю этот код.

2. Это прекрасно работает, сэр, ваша логика удивительна, большое вам спасибо…!!!!!!!!