perms
is an array of objects. Each object is:
{
catg: 'Catg1'
serv: ->array of serv objects
{
checked: false,
desc: 'Serv 1'
}
}
On button click, based on the catg
sent, I need to update all checked to true for each serv
object for that catg
. Code is as below:
const [perms, setPerms] = useState<any[] | null>(null);
const handleClick = (
event: React.MouseEvent,
catg: string
) => {
const permCopy = [...perms];
const catgPerm = permCopy?.filter(function (perm) {
return perm.catg === catg;
});
const catgServs = perms?.servs;
catgServs.map((serv, index) => {
const updatedServ = { ...serv, checked: true };
catgServs[index] = updatedSer;
});
}
setPerms(permCopy);
The screen is not re-rendering and it does not reflect the updated check boxes. I suspect the state variable is not getting updated.
The data looks like this:
perms = [
{
catg: 'Catg1',
servs: [
{
desc: 'Serv1',
checked: false,
},
{
desc: 'Serv2',
checked: false,
},
{
desc: 'Serv3',
checked: false,
}
]
},
{
catg: 'Catg2',
servs: [
{
desc: 'Serv4',
checked: false,
},
{
desc: 'Serv5',
checked: false,
},
{
desc: 'Serv6',
checked: false,
}
]
}
]
catgPerm
array filtered from the perms
state, via permCopy
, but then never uses it.perms
is an array, so perm?.servs
/catgServs
appears to likely be undefined.catgServs
is actually defined, the code runs the Array.map
function but doesn't return new mapped values nor does it save the mapped result. Instead, the map callback is mutating the catgServs
array elements.permCopy
which hasn't any updates at all.// Shallow copy of perms array
const permCopy = [...perms];
// Filtered copy of permCopy, never referenced again
const catgPerm = permCopy?.filter(function (perm) {
return perm.catg === catg;
});
// Direct reference to whatever perms.servs is
// Maybe this was supposed to be `catgPerm[0]?.servs` 🤷🏻♂️
const catgServs = perms?.servs;
// Mutations in mapping callback
catgServs.map((serv, index) => {
const updatedServ = { ...serv, checked: true };
catgServs[index] = updatedSer;
});
// Save the shallow copy of perms array back into state
setPerms(permCopy);
perms
array to a new array reference and shallow copy all
array elements.perms
element by catg
property, you will create a new object reference and shallow copy its properties.servs
array property where each element is a new object reference, setting the checked
property to true
.any
in Typescript is about the least helpful thing you can do; implement and use a basic interface.interface Serv {
checked: boolean;
desc: string;
}
interface Perm {
catg: string;
servs: Serv[];
}
const [perms, setPerms] = useState<Perm[] | null>(null);
const handleClick = (
event: React.MouseEvent,
catg: string
) => {
setPerms(perms => perms.map( // <-- shallow copy perms array
perm => perm.catg === catg
? { // <-- new "Perm" object reference
...perm,
servs: perm.servs.map(serv => ({ // <-- shallow copy servs array
...serv, // <-- new "Serv" object reference
checked: true
}))
}
: perm // <-- non-updated "Perm" object
));
}