using React I’ve been able to update a value of an object stored in the parent component from a onChange()
made in a child component.
However I’m trying to do the same with a component that is created from a list of mapped objects, so it only updates the value in the object list that built that component. I’m failing but here’s an example of what I’m doing:
Parent Component:
const Parent = () => {
const [banners, bannersUpdate] = React.useState([
{
id: 1, name: "banner1", nameSize: 14
},
{
id: 2, name: "banner2", nameSize: 16
},
{
id: 3, name: "banner3", nameSize: 18
}
]);
const handleUpdateNameSize = (id, e) => {
banners.nameSize = e.value
bannersUpdate({
nameSize: banners.nameSize,
...banners
})
}
return(
<section className="banners">
{banners.map(banner =>
<Banner
key={banner.id}
id={banner.id}
name={banner.name}
nameSize={banner.nameSize}
updateNameSize={handleUpdateNameSize}
/>
)}
</section>
);
}
Child component:
const Banner = (props) => {
return (
<div className="banCont">
<h2 style={{fontSize: props.nameSize + 'px'}}>{props.name}</h2>
<input onChange={(e) => props.updateNameSize(props.id, e.target)} className={'slider1-' + props.name} />
</div>
)
}
With the above it doesn’t update the object item relating to that banner, it instead just adds a new object item at the top level with that name and value.
I believe the answer relies somewhere in using the key
and I’ve tried replacing all the banners
with banners[id]
like: banners[id].nameSize = e.value
but for some reason it’s not working to update the value.
Help would be appreciated please, thanks.
2
Answers
Problem:
The problem lies in the incorrect approach to updating the state of a nested object within an array in React. The initial attempt involved directly modifying the array (banners) and then attempting to update the state with an incomplete and incorrect structure, resulting in state inconsistency and unexpected behavior. In React, state updates must be performed immutably to ensure proper reactivity and rendering. This means creating a new array that includes the updated object rather than mutating the existing array directly.
You can read more about this here https://reacttraining.com/blog/state-in-react-is-immutable
your updating function has some issues. First
banners.nameSize = e.value
you are trying to add anameSize
"field" to your banners "array". Instead what you should do is to find the relevant banner using theid
and update itsnameSize
value.Also as the other answer mentions as well. Use
map
to ensure that the state is changed and the component re-renders. Using afind
by the id and then updating the nameSize field will mutate the state and will not cause a re-renderAlso better to follow naming standards for useState updating function. if state is
banners
then the function name likesetBanners