I am working on a react where I am dealing with dynamic number of input fields as I am rendering them using arr.map function. But How can I handle the input onChange method with so many input fields?
Here's my component:
this.props.setsList.map((codeset, index) => (
<Table.Row key={codeset.code_system_id}>
<Table.Cell>{index + 1}</Table.Cell>
<Table.Cell>{codeset.name}</Table.Cell>
<Table.Cell>
<Input
type='text'
className='form-control'
value={codeset.code}
placeholder={translateText('Code')}
onChange={() => this.handleCodeChange(event, index)}
style={{ height: '70%' }}
/>
</Table.Cell>
<Table.Cell>
<Input
type='text'
className='form-control'
value={codeset.description}
placeholder={translateText('Code Description')}
onChange={() => this.handleCodeDescriptionChange(event, index)}
style={{ height: '70%' }}
/>
</Table.Cell>
</Table.Row>
All the input fields may have existing fields or may be empty and one can edit it them semd the edit fields to the API. How can I handle such a case with just 1 handleFunction. Is there a way? Any leads will be appreciated.
In the above code, 2 input boxes are there with initial values from the api.
Data passed into your component should go directly into state. Then each field sends the array index, field name and new value to the handleChange callback.
import { useState } from "react";
// passed in as a prop from the parent component
const data = [
{
name: "foo",
code: "gdfgsd"
},
{
name: "bar",
code: "gfdsgsdfgfd"
}
];
const App = ({ setsList = data }) => {
const [state, setState] = useState(setsList);
const handleChange = (e, i) => {
const { value, name } = e.target;
const newState = [...state];
newState[i] = {
...newState[i],
[name]: value
};
console.log(newState);
setState(newState);
};
return (
<div className="App">
{state.map(({ name, code }, index) => {
return (
<div key={index}>
<label>
name
{": "}
<input
name="name"
value={name}
onChange={(e) => handleChange(e, index)}
/>
</label>
<label>
code
{": "}
<input
name="code"
value={code}
onChange={(e) => handleChange(e, index)}
/>
</label>
</div>
);
})}
</div>
);
};
export default App;
There's also a way that you can render each field dynamically by mapping over the array, and then inner mapping over that array item's keys.
import { useState } from "react";
import { data } from "./data";
const App = ({ setsList = data }) => {
const [state, setState] = useState(setsList);
const handleChange = (e, i) => {
const { value, name } = e.target;
const newState = [...state];
newState[i] = {
...newState[i],
[name]: value
};
console.log(newState);
setState(newState);
};
return (
<table className="App">
<tbody>
{state.map((item, index) => (
<tr key={index}>
{Object.keys(item).map((key) => (
<td key={`${index}-${key}`}>
<label>
{key}
{": "}
<input
name={key}
value={item[key]}
onChange={(e) => handleChange(e, index)}
/>
</label>
</td>
))}
</tr>
))}
</tbody>
</table>
);
};
export default App;