I have this JSON data to loop through the object and generate an input field based on the provide_no or provide_remark value as "Y".
I have successfully looped through the object and generated dynamic input fields.
My main problem is I can’t control the dynamic input field value.
JSON Data :
const jsonData = [
{
id: 1,
name: "Item One",
provide_no: "Y",
provide_remark: "N",
},
{
id: 2,
name: "Item One",
provide_no: "Y",
provide_remark: "Y",
},
{
id: 3,
name: "Item One",
provide_no: "Y",
provide_remark: "N",
},
{
id: 4,
name: "Item One",
provide_no: "Y",
provide_remark: "Y",
},
];
My Component :
const Some = () => {
const [init, setInit] = useState({
id: 0,
count: 0,
count2: 0,
});
const handelChangeCount = (e) => {
setInit({ ...init, id: e.target.id, count: e.target.value }); // this will change the all value of init state
};
const handelChangeCount2 = (e) => {
setInit({ ...init, id: e.target.id, count2: e.target.value }); // this will change the all value of init state
};
return jsonData.map((d) => (
<div key={d.id}>
{d.provide_no === "Y" && (
<input
className="input w-auto"
type="number"
value={init.count}
id={d.id}
name="count"
onChange={(event) => handelChangeCount(event)}
/>
)}
{d.provide_remark === "Y" && (
<input
className="input w-auto"
type="number"
value={init.count2}
id={d.id}
name="count2"
onChange={(event) => handelChangeCount2(event)}
/>
)}
</div>
));
};
export default Some;
I have tried to change the init state with handelChangeCount & handelChangeCount2 function
const handelChangeCount = (e) => {
setInit({ ...init, id: e.target.id, count: e.target.value }); // this will change the all value of init state
};
const handelChangeCount2 = (e) => {
setInit({ ...init, id: e.target.id, count2: e.target.value }); // this will change the all value of init state
};
>Solution :
It seems like you are facing an issue with controlling the values of the dynamic input fields generated based on the JSON data. The problem lies in how you are updating the init state object.
Currently, when you call setInit , you are spreading the existing init state and only updating the specific properties ( count or count2 ) based on the id of the input field. However, this approach is overwriting the entire state object, causing all the input fields to have the same value.
To fix this issue, here’s my code as follows:
const Some = () => {
const [init, setInit] = useState([]);
const handleChangeCount = (e) => {
const { id, value } = e.target;
setInit((prevInit) =>
prevInit.map((item) =>
item.id === parseInt(id) ? { ...item, count: value } : item
)
);
};
const handleChangeCount2 = (e) => {
const { id, value } = e.target;
setInit((prevInit) =>
prevInit.map((item) =>
item.id === parseInt(id) ? { ...item, count2: value } : item
)
);
};
useEffect(() => {
// Initialize the state with the jsonData
setInit(jsonData);
}, []);
return init.map((d) => (
<div key={d.id}>
{d.provide_no === "Y" && (
<input
className="input w-auto"
type="number"
value={d.count || ""}
id={d.id}
name="count"
onChange={handleChangeCount}
/>
)}
{d.provide_remark === "Y" && (
<input
className="input w-auto"
type="number"
value={d.count2 || ""}
id={d.id}
name="count2"
onChange={handleChangeCount2}
/>
)}
</div>
));
};
export default Some;
Hope this would solve your problem.
🙂 David