I am new with react and working on a project where I am using the following
const [skillSet, updateSkillSet] = useState([{
skillType : '',
skillDescr : [
{
skillName : '',
skillExp : ''
}
]
}])
when elements are added array looks like
[
{
"skillType": "fe",
"skillDescr": [
{
"skillName": "s1",
"skillExp": "3"
},
{
"skillName": "s2",
"skillExp": "3"
},
{
"skillName": "s3",
"skillExp": "2"
}
]
},
{
"skillType": "be",
"skillDescr": [
{
"skillName": "b1",
"skillExp": "2"
},
{
"skillName": "b2",
"skillExp": "2"
},
{
"skillName": "b3",
"skillExp": "2"
}
]
}
]
when I add an element to the skillDescr array it's working fine and it's rendering properly in the UI. But when I delete an element from skillDescr, the values that gets removed from the array is correct(the one which I am trying to delete) but in the UI the last element is being removed.
output(UI) after deleting s2,b2
This is the code I am using to delete the element
function deleteSkill(e, index, index1){
e.preventDefault()
skillSet[index].skillDescr = skillSet[index].skillDescr.filter((_,i)=>i!=index1)
updateSkillSet(skillSet)
}
I have index, index1 as there are two arrays I am using map to render the UI
here is the code
{
skillSet.map(({skillType, skillDescr},index)=>{
return(
<div key={index} className='skills__box'>
<div className='skill__type'>
<input placeholder='Skill set name' onChange={(e)=>{updateSkilltype(e,index)}}></input>
{
skillDescr.map(({skillName, skillExp},index1)=>{
return(
<div key={index1} className='skill__name'>
<input placeholder='Skill name' onChange={(e)=>{updateSkillname(e, index, index1)}} required></input>
<input placeholder='Experiece Level' onChange={(e)=>{updateSkillexp(e, index, index1)}} type='number' required></input>
<AiTwotoneDelete onClick={(e)=>{deleteSkill(e, index, index1)}}/>
</div>
)
})
}
<button onClick={(e)=>{addSkill(e,index)}} className='btn btn-primary'>Add skill</button>
</div>
</div>
)
})
}
So my problem here is the array is getting updated properly but the render that's happening after the state update is not correct
That is because React doesn't know which element got removed. You need to add a key
prop to all elements that correspond with the data rendered inside the loop so React can compare properly. Always try to prevent indices as key
's.
Using something unique and stable, like an ID, would be even better.
{
skillSet.map(({skillType, skillDescr},index)=>{
return(
<div key={skillType} className='skills__box'>
<div className='skill__type'>
<input placeholder='Skill set name' onChange={(e)=>{updateSkilltype(e,index)}}></input>
{
skillDescr.map(({skillName, skillExp},index1)=>{
return(
<div key={skillName} className='skill__name'>
<input placeholder='Skill name' onChange={(e)=>{updateSkillname(e, index, index1)}} required></input>
<input placeholder='Experiece Level' onChange={(e)=>{updateSkillexp(e, index, index1)}} type='number' required></input>
<AiTwotoneDelete onClick={(e)=>{deleteSkill(e, index, index1)}}/>
</div>
)
})
}
<button onClick={(e)=>{addSkill(e,index)}} className='btn btn-primary'>Add skill</button>
</div>
</div>
)
})
}