Your solution was almost there, but using the find
method on newList
will only return elements from newList
, not from the items
array within those elements. Also, since you're looking for the value of role
, not the element itself, the find
method isn't the best choice for your current data structure. However, if you're determined to use find
, there is a workaround.
Instead, a simple loop with recursion can achieve the desired result:
/*export*/ const findAfterRefresh = (list, url) => {
for (const item of list) {
if (item.role?.includes(url)) {
return item.role;
}
if (item.items?.length) {
const childRole = findAfterRefresh(item.items, url);
if (childRole) {
return childRole;
}
}
}
};
Here's an annotated version of the code:
/*export*/ const findAfterRefresh = (list, url) => {
// Loop through the given list...
for (const item of list) {
// ...check the role of this item
// (Remove v-- this `?` if `role` will always be there)
if (item.role?.includes(url)) {
return item.role;
}
// If this item has child items, check them recursively
if (item.items?.length) {
// Search child items using recursion
const childRole = findAfterRefresh(item.items, url);
if (childRole) {
// Return the found role
return childRole;
}
// Continue looping if role not found
}
}
};
Live Example:
... (the rest of the code remains the same as in the original text) ...
Note: I made some modifications to the 'role' containing 'role7' so you can see that the code returns the complete 'role', not just the part matching the 'url'.
If you still want to use the find
method, you can first create a flat array of roles:
// Creates a new array of 'role' values including child elements
// (may contain 'undefined' if any 'role' property is missing)
const flattenRoles = (list) =>
(list ?? []).flatMap((item) => [item.role, ...flattenRoles(item.items)]);
/*export*/ const findAfterRefresh = (list, url) => {
return flattenRoles(list).find((role) => role?.includes(url));
};
This code is shorter but generates temporary arrays and traverses the full list before searching for roles, unlike the earlier version which stops at the first match. While this may not matter much for a reasonable list size like 'newList', it's something to keep in mind. (Personally, I'd prefer the earlier version over this one.)
See it in action here:
... (the rest of the code remains the same as in the original text) ...
In response to a comment asking about ESLint rules:
...how much do you think eslint is right in this case?
The decision depends on your requirements. For modern environments supporting ES2015+, 'regenerator-runtime' is unnecessary. As major outdated environments like IE11 are no longer relevant, explicit avoidance of 'regenerator-runtime' might not be needed. If compatibility is crucial and avoiding 'regenerator-runtime' is a priority, you can replace the 'for-of' loop with 'some' for iteration:
... (the continued code remains the same as in the original text) ...
...and the error on 'childRole' from TypeScript is TS7022...
The TypeScript warning results from the lack of type annotations in the JavaScript code provided, as the initial question did not center around TypeScript. Adding appropriate type annotations should resolve the issue without trouble.