I am trying to dynamically add and remove text fields for user entry. When I click the button to remove a particular row, I want to modify the state object to remove the data of that row thereby causing the row to disappear. However I am unable to do that and I am getting an error in the render loop as the compiler is unable to find the value for the row. The error is as follows
Cannot read properties of undefined (reading 'from')
I want it to look at the new state object and display the number of rows accordingly. Here is the code for sandbox
import "./styles.css";
import React from "react";
import { Button, Grid, Paper } from "@mui/material";
import { TextField, Icon } from "@mui/material";
interface State {
serialInputObjects: any;
}
class SerialQRScanClass extends React.PureComponent<State> {
state = {
serialInputObjects: {
0: { from: "", to: "", except: "" }
}
};
//Delete the already registered scanned codes code here
handleAdd = () => {
const objectLength = Object.keys(this.state.serialInputObjects).length;
console.log(objectLength);
this.setState((prevState) => ({
...prevState,
serialInputObjects: {
...prevState.serialInputObjects,
[objectLength]: {
from: "",
to: "",
except: "",
fromError: "",
toError: ""
}
}
}));
console.log(this.state.serialInputObjects);
};
handleChangeFromSerials = (key: any, data: string) => {
this.setState((prevState) => ({
...prevState,
serialInputObjects: {
...prevState.serialInputObjects,
[key]: { ...prevState.serialInputObjects[key], from: data }
}
}));
console.log(this.state.serialInputObjects);
//this.calculation(key);
};
handleChangeToSerials = (key: any, data: string) => {
this.setState((prevState) => ({
...prevState,
serialInputObjects: {
...prevState.serialInputObjects,
[key]: { ...prevState.serialInputObjects[key], to: data }
}
}));
console.log(this.state.serialInputObjects);
//this.calculation(key);
};
handleRemove = (key) => {
console.log(this.state.serialInputObjects);
this.setState((prevState) => ({
...prevState,
serialInputObjects: { ...prevState.serialInputObjects, [key]: undefined }
}));
console.log(this.state.serialInputObjects);
};
render() {
return (
<Paper elevation={3} className="abc">
<Button onClick={this.handleAdd}>ADD NEW FIELD</Button>
{Object.keys(this.state.serialInputObjects).map((key) => (
<div key={key}>
<Grid container alignItems="flex-end">
<Grid item className="bcd">
<TextField
fullWidth
label={"FROM"}
placeholder={"Ex.100"}
value={this.state.serialInputObjects[key]["from"]}
onChange={(e) =>
this.handleChangeFromSerials(key, e.target.value)
}
error={
Boolean(this.state.serialInputObjects[key]["fromError"]) ||
false
}
helperText={this.state.serialInputObjects[key]["fromError"]}
margin="none"
size="small"
/>
</Grid>
<Grid item className="bcd">
<TextField
fullWidth
label={"To"}
placeholder={"Ex.100"}
value={this.state.serialInputObjects[key]["to"]}
onChange={(e) =>
this.handleChangeToSerials(key, e.target.value)
}
error={
Boolean(this.state.serialInputObjects[key]["toError"]) ||
false
}
helperText={this.state.serialInputObjects[key]["toError"]}
margin="none"
size="small"
/>
</Grid>
<Grid
item
className={"abc"}
style={{ paddingLeft: "10px" }}
></Grid>
<div style={{ display: key === "0" ? "none" : "block" }}>
<Button onClick={(e) => this.handleRemove(key)}>
<Icon fontSize="small">remove_circle</Icon>
</Button>
</div>
</Grid>
</div>
))}
</Paper>
);
}
}
export default function App() {
return (
<div className="App">
<SerialQRScanClass />
</div>
);
}