I'm trying to build a component which works like a selection tree, but with the possibility for users to edit each row in the selection tree.
Basically, a component where you can keep drilling down to get more details.
The data is structured like a nested object, where an item with drilldown possibilities has a children as per below.
const [categories, setCategories] = useState([
{
name: "First Tier",
identifier: "1",
children: [
{
name: "Second Tier",
identifier: "2",
children: [
{
name: "Third Tier",
identifier: "3",
children: [
{
name: "Fourth Tier",
identifier: "4",
children: [{ name: "Fifth Tier", identifier: "5" }],
},
],
},
],
},
],
},
{ name: "Another top tier", identifier: "6" },
{ name: "a Third top tier", identifier: "7" },
]);
My challenge is that I can't seem to find a way to modify the child and the props as I wish. As an example, I would like to be able to modify the name of the fifth child to some random name. Note - I wish to be able to modify whatever child, and I will have the identifier available.
As I'm using react, it needs to be done using "useState", which makes it a little bit more tricky according to my understanding.
Any ideas or anyone been through this challenge?
Presented below is one possible way to achieve the desired objective.
Code Snippet
const findAndUpdate = (id, val, arr) => {
// find 'arr' element with matching identifier
const tgtObj = arr.find(
({ identifier }) => identifier === id
);
if (tgtObj) { // found identifier, so update the name
tgtObj.name = val; // this will mutate the original array passed as argument
} else { // not found, recurse through 'children' array
arr.filter(el => 'children' in el).forEach(
({ children }) => findAndUpdate(id, val, children)
);
};
return arr; // in all cases, return 'arr' as-is
};
const stateArr = [
{
name: "First Tier",
identifier: "1",
children: [
{
name: "Second Tier",
identifier: "2",
children: [
{
name: "Third Tier",
identifier: "3",
children: [
{
name: "Fourth Tier",
identifier: "4",
children: [{ name: "Fifth Tier", identifier: "5" }],
},
],
},
],
},
],
},
{ name: "Another top tier", identifier: "6" },
{ name: "a Third top tier", identifier: "7" },
];
// the 'stateArr' will be mutated by using this method
console.log(
'find id: 5 and update name: "New Fifth Tier"... ',
findAndUpdate("5", "New Fifth Tier", stateArr)
);
// to call this using "setCategories", simply try this:
/*
setCategories(prev => findAndUpdate("5", "New Fifth Tier", prev));
*/
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Inline comments added to the snippet above.