Home > Software design >  Removing an element recursively (React)
Removing an element recursively (React)

Time:11-10

I have an array of nested objects. I'm trying to remove the element I need from it. If I pass an element that is not nested, then everything is ok. But if I try to delete the nested one, it doesn't work. Tell me where is the mistake

import React, { useState, useEffect } from 'react';

let array = [
  {
    id: 1,
    title: 'text 1',
    children: [
      {
        id: 5,
        title: 'text 5',
        children: [],
      },
      {
        id: 6,
        title: 'text 6',
        children: [],
      },
    ],
  },
  {
    id: 2,
    title: 'text 2',
    children: [],
  },
  {
    id: 3,
    title: 'text 3',
    children: [
      {
        id: 7,
        title: 'text 7',
        children: [],
      },
    ],
  },
  {
    id: 4,
    title: 'text 4',
    children: [],
  },
];

export const Component = () => {
  const [state, setState] = useState(array);

  const onDelete = (arr, id) => {
    let result = [...arr].filter((item) => {
      if (item.id !== id) {
        return item;
      } else {
        item.children.length && onDelete(item.children, id);
      }
    });
    setState(result);
  };

  useEffect(() => {
    onDelete(state, 5);
  }, []);

  return <div></div>;
};

I have an array of nested objects. I'm trying to remove the element I need from it. If I pass an element that is not nested, then everything is ok. But if I try to delete the nested one, it doesn't work. Tell me where is the mistake

CodePudding user response:

We can use a generic deep filtering function that accepts a predicate function and recurs on children. This would let us do all sorts of other things: remove all nodes with an odd value in one field, or keep only those with a particular value in another field. For our case, we can then make onDelete a simple wrapper to that filtering function. The code might look like this:

const deepFilter = (pred) => (xs) =>
  xs .flatMap (({children = [], ...rest}) => 
    pred (rest)
      ? [{... rest, children: deepFilter (pred) (children)}]
      : []
  )

const onDelete = (arr, id) =>
  deepFilter (x => x.id !== id) (arr)

let array = [{id: 1, title: "text 1", children: [{id: 5, title: "text 5", children: []}, {id: 6, title: "text 6", children: []}]}, {id: 2, title: "text 2", children: []}, {id: 3, title: "text 3", children: [{id: 7, title: "text 7", children: []}]}, {id: 4, title: "text 4", children: []}]

console .log ('original: ', array)
console .log ('after removing 3: ', onDelete (array, 3))
console .log ('after removing 5: ', onDelete (array, 5))
.as-console-wrapper {max-height: 100% !important; top: 0}

  • Related