I am trying to build a form with some nested data update. The code is as below:
On Change method
let student = {
name: null,
marks: { english: null },
};
const handleChange = (updatedValue) => {
student = {
...student,
...updatedValue,
marks: { ...updatedValue.marks },
};
console.log(student);
};
And my JSX:
<input
type="text"
className="form-control"
id="name"
placeholder="Name"
value={student.name ?? ""}
onChange={(event) =>
handleChange({
name: event.target.value,
})
}
/>
<input
type="text"
className="form-control"
id="english"
placeholder="English"
value={student.marks.english ?? ""}
onChange={(event) =>
handleChange({
marks: { english: event.target.value },
})
}
/>
The problem is that for "name" it works fine. But for "english", it behaves abnormally. E.g. when I enter "1" in English, it updates it to 1 in the console but on the UI, it immediately disappears from the input box. Also if I update it to 2, the value is replaced from one to 2.
The the expected value is 1
Can someone please help me identifying how to update the nested values correctly from the input box?
CodePudding user response:
you must use state to store data
let student = {
name: null,
marks: { english: null },
};
change to
const [student, setStudent] = useState({
name: null,
marks: { english: null },
});
const handleChange = (updatedValue) => {
setStudent(student => ({
...student,
...updatedValue,
marks: { ...student.marks, ...updatedValue.marks },
}))
};
CodePudding user response:
try this code and also here is codesandbox
import React, { useState } from "react";
export default function Form({ addStudent }) {
let [student, setStudent] = useState({
id: "",
name: "",
course: "",
sem: "",
marks: { english: "", maths: "", science: "" }
});
const handleChange = (value) => {
const tempStudent = { ...student, ...value };
setStudent(tempStudent);
};
const handleMarksChange = (value) => {
const tempStudent = { ...student, marks: { ...student.marks, ...value } };
setStudent(tempStudent);
};
return (
<>
<form>
<div className="container form-group">
<div className="row">
<div className="col-6">
<label htmlFor="id" className="ms-2">
ID
</label>
<input
type="number"
className="form-control"
id="id"
placeholder="ID"
value={student.id || ""}
onChange={(event) => {
handleChange({ id: event.target.value });
}}
/>
</div>
<div className="col-6">
<label htmlFor="name" className="ms-2">
Name
</label>
<input
type="text"
className="form-control"
id="name"
placeholder="Name"
value={student.name ?? ""}
onChange={(event) => handleChange({ name: event.target.value })}
/>
</div>
<div className="col-6">
<label htmlFor="course" className="ms-2">
Course
</label>
<input
type="text"
className="form-control"
id="course"
placeholder="Course"
value={student.course ?? ""}
onChange={(event) =>
handleChange({
course: event.target.value
})
}
/>
</div>
<div className="col-6">
<label htmlFor="sem" className="ms-2">
Semmester
</label>
<input
type="text"
className="form-control"
id="sem"
placeholder="Semmester"
value={student.sem ?? ""}
onChange={(event) => handleChange({ sem: event.target.value })}
/>
</div>
<span className="fw-bold mt-2 ms-2">Marks</span>
<div className="col-6">
<label htmlFor="maths" className="ms-2">
Maths
</label>
<input
type="number"
className="form-control"
id="maths"
placeholder="Maths"
value={student.marks.maths ?? ""}
onChange={(event) =>
handleMarksChange({
maths: event.target.value
})
}
/>
</div>
<div className="col-6">
<label htmlFor="English" className="ms-2">
English
</label>
<input
type="text"
className="form-control"
id="english"
placeholder="English"
value={student.marks.english ?? ""}
onChange={(event) =>
handleMarksChange({
english: event.target.value
})
}
/>
</div>
<div className="col-6">
<label htmlFor="science" className="ms-2">
Science
</label>
<input
type="science"
className="form-control"
id="science"
placeholder="Science"
value={student.marks.science ?? ""}
onChange={(event) =>
handleMarksChange({
science: event.target.value
})
}
/>
</div>
</div>
</div>
</form>
</>
);
}
Hope this will give you output in your console.
And You need to use state to pass value
to the input.