Я бы разделил рекурсивный код, который находит список потомков из кода, который выполняет манипуляции с данными. Вот одна возможность:
const descendants = (array, root) =>
[
root,
...array .filter (({parent_id}) => parent_id == root)
.flatMap (({id}) => descendants (array, id))
]
const changeBranch = (fn) => (array, root, keys = descendants (array, root)) =>
array .map (element => keys .includes (element .id) ? fn (element) : element)
const makeInvisible = changeBranch (
({visible, ...rest}) => ({...rest, visible: false})
)
const array = [{ id: 1, parent_id: 0, visible: true }, { id: 2, parent_id: 0, visible: true }, { id: 3, parent_id: 1, visible: true }, { id: 4, parent_id: 3, visible: true }, { id: 5, parent_id: 4, visible: true }, { id: 6, parent_id: 4, visible: true }, { id: 7, parent_id: 3, visible: true }, { id: 8, parent_id: 2, visible: true }];
console .log (makeInvisible (array, 4))
console .log (makeInvisible (array, 2))
.as-console-wrapper {min-height: 100% !important; top: 0}
descendants
находит идентификаторы предоставленного root id и всех узлов-потомков внутри вашего массива.
changeBranch
принимает функцию для преобразования узла и возвращает функцию, которая принимает массив и root id, и возвращает новый массив, содержащий либо результат применения этой функции (когда узел является потомком root) или исходного значения (если это не так.)
makeInvisible
является результатом применения к changeBranch
функции, которая устанавливает * От 1023 * до false
. Это последняя функция, которую вы ищете.
Обратите внимание, что если ваш список циклический c, а не иерархический, это не сработает. Ваш стек, вероятно, переполнится.