Реагировать. js фильтр поиска в виде дерева - PullRequest
0 голосов
/ 19 апреля 2020

Я занимаюсь практикой новичков в React. js и создал компонент вида дерева с помощью material-ui. Теперь я хочу реализовать панель поиска для поиска введенного ключевого слова в виде дерева. Вот мои примеры данных:

[
    {
        id: 1,
        name: "Item 1",
        children: [
            {
                id: 2,
                name: "Subitem 1",
                children: [
                    {
                        id: 3,
                        name: "Misc 1",
                        children: [
                            {
                                id: 4,
                                name: "Misc 2"
                            }
                        ]
                    }
                ]
            },
            {
                id: 5,
                name: "Subitem 2",
                children: [
                    {
                        id: 6,
                        name: "Misc 3",
                    }
                ]
            }
        ]
    },
    {
        id: 7,
        name: "Item 2",
        children: [
            {   
                id: 8,
                name: "Subitem 1",
                children: [
                    {
                        id: 9,
                        name: "Misc 1"
                    }
                ]
            },
            {
                id: 10,
                name: "Subitem 2",
                children: [
                    {
                        id: 11,
                        name: "Misc 4"
                    },
                    {
                        id: 12,
                        name: "Misc 5"
                    },
                    {
                        id: 13,
                        name: "Misc 6",
                        children: [
                            {
                                id: 14,
                                name: "Misc 7"
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

Рендеринг работает должным образом.

const getTreeItemsFromData = treeItems => {
    return treeItems.map(treeItemData => {
        let children = undefined;
        if (treeItemData.children && treeItemData.children.length > 0) {
            children = getTreeItemsFromData(treeItemData.children);
        }
        return(
            <TreeItem
                key={treeItemData.id}
                nodeId={treeItemData.id}
                label={treeItemData.name}
                children={children}/>
        );
    });
};

const DataTreeView = ({ treeItems }) => {
    return(
        <TreeView
            defaultCollapseIcon={<ExpandMoreIcon />}
            defaultExpandIcon={<ChevronRightIcon />}
            >
            {getTreeItemsFromData(treeItems)}
        </TreeView>
    );
};

class App extends Component {
    render() {
        return (
            <div className="App">
               <DataTreeView treeItems={searchedNodes} />
            </div>
        );
    }
}

Сейчас я изо всех сил пытаюсь реализовать функцию поиска. Я хочу использовать панель поиска материалов (https://openbase.io/js/material-ui-search-bar)

1 Ответ

1 голос
/ 19 апреля 2020

В этом решении предполагается, что вы используете уникальный id для каждого элемента в дереве.

Используется алгоритм Поиск в глубину .

Перед попыткой исправьте образцы данных не уникальные идентификаторы. Сначала я их не заметил и потратил время на отладку без ошибок.

function dfs(node, term, foundIDS) {
  // Implement your search functionality
  let isMatching = node.name && node.name.indexOf(term) > -1;

  if (Array.isArray(node.children)) {
    node.children.forEach((child) => {
      const hasMatchingChild = dfs(child, term, foundIDS);
      isMatching = isMatching || hasMatchingChild;
    });
  }

  // We will add any item if it matches our search term or if it has a children that matches our term
  if (isMatching && node.id) {
    foundIDS.push(node.id);
  }

  return isMatching;
}

function filter(data, matchedIDS) {
  return data
    .filter((item) => matchedIDS.indexOf(item.id) > -1)
    .map((item) => ({
      ...item,
      children: item.children ? filter(item.children, matchedIDS) : [],
    }));
}

function search(term) {
  // We wrap data in an object to match the node shape
  const dataNode = {
    children: data,
  };

  const matchedIDS = [];
  // find all items IDs that matches our search (or their children does)
  dfs(dataNode, term, matchedIDS);

  // filter the original data so that only matching items (and their fathers if they have) are returned
  return filter(data, matchedIDS);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...