Получать дочерние узлы асинхронно с сервера при нажатии родителя

Мотивация

Я писал эту функциональность как часть требования к работе по отображению иерархии организации. Это оказалось сложнее, чем я сначала ожидал. Постановка задачи заключалась в том, чтобы структурировать данные, которые мы извлекли из внутреннего API, и отобразить их в компоненте TreeView из пользовательского интерфейса материала. Нам приходилось получать большие объемы данных, поэтому все дерево не могло быть загружено сразу. Нам нужно было извлекать дочерние узлы один за другим из серверной части, когда пользователь нажимает кнопку Развернуть.

Решение

Я решил проблему, используя комбинацию реквизитов selected и expanded из TreeView API. В этом примере мы асинхронно загружаем новые дочерние элементы и расширяем родителя после их загрузки. Чтобы иметь возможность хранить эти данные в памяти, нам также необходимо использовать структуру данных графа (единственный раз, когда структура данных была мне полезна, кроме собеседования с инженером). В моем примере я вызываю структуру данных TreeNode, и у нее есть различные методы, такие как traverse, addNode и searchByName:

Так что же здесь происходит? Ну, во-первых, мы начнем с объявления класса, который является просто синтаксическим сахаром вокруг старого способа объявления функций в JavaScript. Класс позволяет нам определять члены класса и конструктор для инициализации экземпляров класса. Каждый экземпляр класса TreeNode имеет id, root, name и children. Корень указывает на самый первый узел в графике. Дети являются указателями на следующие узлы в графике. Идентификатор — это уникальный идентификатор, а имя — это метка, которую мы будем отображать на экране. Функция обхода позволяет нам посетить каждый узел в графе, а также предлагает функцию обратного вызова, что означает, что мы можем выполнить некоторую операцию на каждом узле в графе. Например, при добавлении нового дочернего узла к определенному родительскому узлу мы проходим весь график, пока не найдем id родительского узла, а затем добавляем новый дочерний узел (как сами TreeNode) в массив дочерних элементов родительского узла.

Теперь, когда структура данных готова к использованию, мы можем работать над реализацией презентационных частей пользовательского интерфейса. Предполагая, что вы уже загрузили свой проект с помощью create-react-app, остальное довольно просто.

Мы начинаем с компонента TreeView из Material UI в качестве внешнего JSX. В качестве реквизита нам нужно передать defaultCollapseIcon, defaultExpandIcon, selected, onNodeSelect и expanded в TreeView. Первые два — это просто значки SVG, selected отслеживает текущий выбранный узел, expanded — это массив id, чьи дочерние узлы в настоящее время развернуты на экране, а onNodeSelect — это функция, вызываемая при выборе нового узла. Внутри TreeView нам нужно создать файл TreeItems. Мы можем рекурсивно (опять же, это один из немногих случаев, когда мне приходилось использовать рекурсию вне интервью) вызвать createItemsFromTree, чтобы добавить все нужные нам TreeItem. Функция handleChange — это обработчик событий для расширения/убирания узла в дереве при нажатии. Он выполняет вызов asynchronous к внутреннему API, чтобы получить дочерние элементы родительского узла, а затем отображает их после завершения вызова API. Чтобы отслеживать состояние в компоненте, мы используем хук useState из react для создания 3 частей состояния: expanded, selected и tree. Подключите компонент TreeViewDemo к вашему вызову ReactDOM.render, и вы увидите дерево в действии, как показано ниже:

Заключение

Это демонстрационное решение поможет вам пройти около 80% пути. Другие соображения, которые необходимо принять во внимание, включают реализацию фактического вызова API, виртуализацию элементов TreeItem DOM в случае бесконечно большого дерева, стилизацию компонента и добавление атрибутов доступности к базовым элементам HTML. Если вам нравится мой стиль письма, пожалуйста, следуйте. Я публикую ~ 1 раз в месяц, и мне нравится общаться в сети, спасибо