TL;DR Lodash has a helper for drilling down into nested objects and arrays, but only using keys and indexes, not properties of items in arrays. You'd need to make your own function for this.
Assuming that your id pattern holds and each id contains the ancestor ids (where '1.3.1' is a child of '1.3', which is a child of '1', etc.), then you'll want to split that id by your chosen delineator (. in this case) to create a path to search along. I'm also assuming that you would be using strings for the id properties, since a number type isn't going to permit multiple . characters.
const idToFind = '1.1';
const path = idToFind.split('.');
>> ['1', '1']
After that, you'll need to incrementally use more items from the list to create matching ids. If you keep track of the depth, you can slice the array to include the desired ids. Additionally, you'll want to abort the iteration if a matching id isn't found. This can be accomplished using a while loop to iterate over your path array while you haven't reached the max "depth" (the length of the path).
let children = data;
let depth = 1;
let obj = null; // keeps track of matching objects
while (depth <= path.length) {
const id = path.slice(0, depth).join('.');
obj = _.find(children, (elem) => elem.id === id);
if (!obj) return false;
children = obj.children;
depth += 1;
}
By the end of this iteration, you will have either returned false because we hit a non-matching id at some point, or we'll have our desired element as obj. From there, you can set the text value.
function updateText(data, idToFind, value) {
const path = idToFind.split('.');
let children = data;
let depth = 1;
let obj = null; // keeps track of matching objects
while (depth <= path.length) {
const id = path.slice(0, depth).join('.');
obj = _.find(children, (elem) => elem.id === id);
if (!obj) return false;
children = obj.children;
depth += 1;
}
obj.text = value;
return true;
}
This approach has the advantage of aborting the loop as soon as any unmatched id is found at each level. It also makes more use of the id pattern you have by looking for a matching id at each leve. The solution posted by georg will work, but it's going to loop through every element and nested child element until it finds the one you're looking for, so it's going to take longer with more complex data structures.
.filter+.mapto update them in-place.