I have 2 dynamic inputs academic and teaching exp but only academic works
and when I try to add a new field to teachingExp it returns typeError: teachingExp.map is not a
function
i have used the same code for both dynamic inputs but one works and other does not
both these input divs are inside a form
outside component return
const [academic, setAcademic] = useState([
{
degree: "",
branch: "",
university: "",
completionYear: "",
grade: "",
},
]);
const [teachingExp, setTeachingExp] = useState([
{
university: "",
designation: "",
period: "",
},
]);
const handleAcademicChange = (index, e) => {
let data = [...academic];
data[index][e.target.id] = e.target.value;
setAcademic(data);
};
const handleTeachingExpChange = (index, e) => {
let data = [...teachingExp];
data[index][e.target.name] = e.target.value;
setTeachingExp(data);
};
const addAcademic = () => {
let newAcademic = {
degree: "",
branch: "",
university: "",
completionYear: "",
grade: "",
};
setAcademic([...academic, newAcademic]);
};
const addTeachingExp = () => {
let newTeachingExp = {
university: "",
designation: "",
period: "",
};
setTeachingExp(...teachingExp, newTeachingExp);
};
const removeAcademic = (index) => {
let data = [...academic];
data.splice(index, 1);
setAcademic(data);
};
const removeTeachingExp = (index) => {
let data = [...teachingExp];
data.splice(index, 1);
setTeachingExp(data);
};
inside return
<div className="flex justify-center w-full m-auto my-6 p-4 font-sans ">
<div className="flex flex-col p-3">
<h3 className="text-center p-3 text-3xl font-medium text-gray-700 mb-5 ">
Academic Qualifications
</h3>
{academic.map((input, index) => {
return (
<div
key={index}
className="w-56 mb-4 relative group grid place-content-center place-items-center m-auto lg:grid-flow-col gap-4 "
>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">Degree/Title</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
id="degree"
autoComplete="true"
placeholder="Enter degree"
value={input.degree}
onChange={(e) => handleAcademicChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">
Branch/Specialization
</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
id="branch"
autoComplete="true"
placeholder="Enter branch"
value={input.branch}
onChange={(e) => handleAcademicChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">
University/College
</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
id="university"
autoComplete="true"
placeholder="Enter university"
value={input.university}
onChange={(e) => handleAcademicChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">
Completion year
</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
id="completedYear"
autoComplete="true"
placeholder="Enter completion year"
value={input.completedYear}
onChange={(e) => handleAcademicChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">Grade/Marks</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
id="grade"
autoComplete="true"
placeholder="Enter grade"
value={input.grade}
onChange={(e) => handleAcademicChange(index, e)}
/>
</div>
{academic.length > 1 ? (
<TrashIcon
className="h-8 mt-5 mx-4 text-red-600"
onClick={() => removeAcademic(index)}
/>
) : (
""
)}
</div>
);
})}
<PlusCircleIcon
className="h-12 p-2 mx-4 text-[#020493] mt-1"
onClick={addAcademic}
/>
</div>
</div>
<div className="flex justify-center w-full m-auto my-6 p-4 font-sans ">
<div className="flex flex-col p-3">
<h3 className="text-center p-3 text-3xl font-medium text-gray-700 mb-5 ">
Teaching Experience
</h3>
{teachingExp.map((input, index) => (
<div
key={index}
className="w-56 mb-4 relative group grid place-content-center place-items-center m-auto lg:grid-flow-col gap-4 "
>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">
University/College
</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
name="university"
autoComplete="true"
placeholder="Enter university"
value={input.university}
onChange={(e) => handleTeachingExpChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">Designation</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
name="designation"
autoComplete="true"
placeholder="Enter designation"
value={input.designation}
onChange={(e) => handleTeachingExpChange(index, e)}
/>
</div>
<div className="w-56 lg:w-40 p-2 xl:w-56">
<label className="text-sm font-light">Period</label>
<input
className="form-control
block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none "
type="text"
required
name="period"
autoComplete="true"
placeholder="Enter period"
value={input.period}
onChange={(e) => handleTeachingExpChange(index, e)}
/>
</div>
{teachingExp.length > 1 ? (
<TrashIcon
className="h-8 mt-5 mx-4 text-red-600"
onClick={() => removeTeachingExp(index)}
/>
) : (
""
)}
</div>
))}
<PlusCircleIcon
className="h-12 p-2 mx-4 text-[#020493] mt-1"
onClick={addTeachingExp}
/>
</div>
</div>
>Solution :
You are not properly updating state when adding new. Rewrite to this:
const addTeachingExp = () => {
let newTeachingExp = {
university: "",
designation: "",
period: "",
};
setTeachingExp([...teachingExp, newTeachingExp]); // HERE YOU FORGOT TO SPREAD IT INTO NEW ARRAY
};