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?
CodePudding user response:
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.