Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

225
Vistas
El formulario dinámico devuelve el mismo valor para la primera y la segunda entrada

Estoy creando un formulario dinámico personalizado usando la biblioteca Material UI https://mui.com/ como componente para mi aplicación React Js.

Aquí está el estado inicial del componente de formulario dinámico. ingrese la descripción de la imagen aquí

Como podemos ver, el componente de formulario dinámico comienza solo con un formulario de punto de entrega. Podríamos agregar otro formulario de punto de entrega haciendo clic en el botón "Agregar entrega". Aquí está el ejemplo después de hacer clic en el botón "Agregar entrega".

ingrese la descripción de la imagen aquí

El problema es: el primer formulario y el segundo formulario tienen los mismos valores (si hay más de 1 formulario) después de que le dimos entrada a uno de los primeros o segundos formularios como se ve en la captura de pantalla a continuación. Esta no es la condición que quiero.

ingrese la descripción de la imagen aquí

Pero las formas restantes (tercera, cuarta, etc.) son únicas, como se ve en la siguiente captura de pantalla. Esta es la condición que quiero.

ingrese la descripción de la imagen aquí

Aquí está el código de trabajo simple:

DeliveryPoint.jsx

 const DeliveryPoint = (props) => { const { initialFormObject, formObject, setFormObject, collapseObject, setCollapseObject } = props; const classes = useStyles(); const deliveryPointBaseObject = initialFormObject.deliveryPointList[0]; const handleFormObjectChange = (inputEvent, inputIndex) => { let deliveryPointListData = [...formObject.deliveryPointList]; deliveryPointListData[inputIndex][inputEvent.target.name] = inputEvent.target.value; setFormObject((current) => ({ ...current, deliveryPointList: deliveryPointListData })); }; const handleDatePickerChange = (inputNewValue, inputIndex) => { let deliveryPointListData = [...formObject.deliveryPointList]; deliveryPointListData[inputIndex].deliveryDate = inputNewValue; setFormObject((current) => ({ ...current, deliveryPointList: deliveryPointListData })); }; const handleCollapseChange = (inputIndex) => { let deliveryPointListData = [...collapseObject.deliveryPointList]; deliveryPointListData[inputIndex] = !deliveryPointListData[inputIndex]; setCollapseObject((current) => ({ ...current, deliveryPointList: deliveryPointListData })); }; const handleAddFormItemButtonClick = () => { let deliveryPointListData = [...formObject.deliveryPointList]; deliveryPointListData.push(deliveryPointBaseObject); setFormObject((current) => ({ ...current, deliveryPointList: deliveryPointListData })); deliveryPointListData = [...collapseObject.deliveryPointList]; deliveryPointListData.push(false); setCollapseObject((current) => ({ ...current, deliveryPointList: deliveryPointListData })); }; const handleDeleteFormItemButtonClick = (inputIndex) => { let deliveryPointListData = [...formObject.deliveryPointList]; deliveryPointListData.splice(inputIndex, 1); setFormObject((current) => ({ ...current, deliveryPointList: deliveryPointListData })); deliveryPointListData = [...collapseObject.deliveryPointList]; deliveryPointListData.splice(inputIndex, 1); setCollapseObject((current) => ({ ...current, deliveryPointList: deliveryPointListData })); }; return ( <> {formObject.deliveryPointList.map((item, index) => ( <Box key={index} className={classes.formItemContainer}> <Box className={classes.formItemTitleContainer}> {/* TITLE */} <Typography variant="h6"> {index === 0 ? `Delivery point` : `#${index + 1} Delivery point`} </Typography> {/* ADD OR DELETE BUTTON */} {index === 0 ? ( <Button className={classes.formItemTitleButton} variant="outlined" startIcon={<IconAdd />} onClick={handleAddFormItemButtonClick} > Add Delivery </Button> ) : ( <Button className={classes.formItemTitleButton} variant="outlined" startIcon={<IconRemove />} color="error" onClick={() => handleDeleteFormItemButtonClick(index)} > Remove Delivery </Button> )} </Box> {/* CONSIGNEE */} <FormControl required variant="outlined" className={classes.formItemInput} > <InputLabel>Consignee</InputLabel> <OutlinedInput label="Consignee" type="text" name="consignee" value={item.consignee} onChange={(event) => handleFormObjectChange(event, index)} /> <FormHelperText> Search for name, street, city, or state by typing in the box. </FormHelperText> </FormControl> {/* DELIVERY DATE */} <LocalizationProvider dateAdapter={AdapterDateFns}> <DatePicker disableFuture label="Select Delivery Date" openTo="year" views={["year", "month", "day"]} value={item.deliveryDate} onChange={(newValue) => handleDatePickerChange(newValue, index)} renderInput={(params) => ( <TextField required className={classes.formItemInput} {...params} /> )} /> </LocalizationProvider> {/* COLLAPSE */} <Collapse in={collapseObject.deliveryPointList[index]} timeout="auto" unmountOnExit className={classes.formItemCollapse} > {/* DELIVERY INSTRUCTION */} <FormControl variant="outlined" className={classes.formItemInput}> <InputLabel>Delivery Instructions</InputLabel> <OutlinedInput label="Delivery Instructions" type="text" name="deliveryInstruction" value={item.deliveryInstruction} onChange={(event) => handleFormObjectChange(event, index)} /> </FormControl> </Collapse> {/* EXPAND BUTTON */} <Button variant="contained" disableElevation startIcon={ collapseObject.deliveryPoint ? ( <IconArrowDropUp /> ) : ( <IconArrowDropDown /> ) } className={classes.formItemButtonExpand} onClick={() => handleCollapseChange(index)} > {collapseObject.deliveryPoint ? "Hide full data entry" : "Fill in more complete data?"} </Button> </Box> ))} </> ); }; export default DeliveryPoint;

Aplicación.jsx

 const App = () => { const classes = useStyles(); const initialFormObject = { // DELIVERY POINT deliveryPointList: [ { consignee: "", deliveryDate: new Date(), deliveryInstruction: "" } ] // OTHER OBJECT ITEMS HERE }; const initialCollapseObject = { deliveryPointList: [false] // OTHER LIST ITEMS HERE }; const [formObject, setFormObject] = useState(initialFormObject); const [collapseObject, setCollapseObject] = useState(initialCollapseObject); return ( <Box className={classes.pageRoot}> {/* FORM */} <Box className={classes.formContainer}> {/* DELIVERY POINT */} <DeliveryPoint initialFormObject={initialFormObject} formObject={formObject} setFormObject={setFormObject} collapseObject={collapseObject} setCollapseObject={setCollapseObject} /> </Box> </Box> ); }; export default App;

Aquí está la demostración completa https://codesandbox.io/s/stackoverflow-dynamic-form-wxrmd0

Pasos para reproducir:

  1. Haga clic en el botón "Agregar entrega" dos veces. Así que habrá 3 formularios de punto de entrega.
  2. Cambiar el "destinatario" o la "fecha de entrega" en el formulario del primer punto de entrega. Por lo tanto, el segundo formulario de punto de entrega tendrá el mismo valor que el primer formulario.

¿Qué le pasa a mi gestión estatal y cuál es la solución para esto?

Nota: puede asumir el componente OultinedInput de Material UI como un elemento input HTML.

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Asunto

Está mutando el estado en sus handleFormObjectChange y handleDatePickerChange .

 const handleFormObjectChange = (inputEvent, inputIndex) => { let deliveryPointListData = [...formObject.deliveryPointList]; // Mutates the nested property!! deliveryPointListData[inputIndex][inputEvent.target.name] = inputEvent.target.value; setFormObject((current) => ({ ...current, deliveryPointList: deliveryPointListData })); }; const handleDatePickerChange = (inputNewValue, inputIndex) => { let deliveryPointListData = [...formObject.deliveryPointList]; // Mutates the nested property!! deliveryPointListData[inputIndex].deliveryDate = inputNewValue; setFormObject((current) => ({ ...current, deliveryPointList: deliveryPointListData })); };

Solución

Asegúrese de copiar superficialmente todas las propiedades y las propiedades anidadas que se actualizan. Esto garantiza que todas las actualizaciones creen nuevas referencias de objetos.

 const handleFormObjectChange = (inputEvent, inputIndex) => { let deliveryPointListData = [...formObject.deliveryPointList]; deliveryPointListData[inputIndex] = { ...deliveryPointListData[inputIndex], // <-- shallow copy [inputEvent.target.name]: inputEvent.target.value }; setFormObject((current) => ({ ...current, deliveryPointList: deliveryPointListData })); }; const handleDatePickerChange = (inputNewValue, inputIndex) => { let deliveryPointListData = [...formObject.deliveryPointList]; deliveryPointListData[inputIndex] = { ...deliveryPointListData[inputIndex], // <-- shallow copy deliveryDate: inputNewValue, }; setFormObject((current) => ({ ...current, deliveryPointList: deliveryPointListData })); };

Editar formulario dinámico devuelve el mismo valor para la primera y la segunda entrada

over 4 years ago · Santiago Trujillo Denunciar

0

No está haciendo una copia de deliveryPointBaseObject. Pero, repitiéndolo. Por lo tanto, obtiene el mismo valor para los primeros 2. Cambiarlo por debajo de uno corrige su problema de mutación.

const deliveryPointBaseObject = {...initialFormObject.deliveryPointList[0]};

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda