diff --git a/hierarchy_manager.libraries.yml b/hierarchy_manager.libraries.yml
index 39c511b7c2a63c398df3efaebb32af24b99c1f68..e4db988588a500b9c2657f04d40d6032f634c5b4 100644
--- a/hierarchy_manager.libraries.yml
+++ b/hierarchy_manager.libraries.yml
@@ -10,6 +10,7 @@ feature.hm.jstree:
     - hierarchy_manager/libraries.jquery.jstree
     - core/drupalSettings
     - core/drupal.message
+    - core/once
 
 feature.hm.jsoneditor:
   js:
diff --git a/js/Plugin/jstree/hm.jstree.js b/js/Plugin/jstree/hm.jstree.js
index ed9b21b75580a5993efb8442623ebac5e4f38cdc..b87e959fff53b3497b27e60d91b06ac1710f9b34 100644
--- a/js/Plugin/jstree/hm.jstree.js
+++ b/js/Plugin/jstree/hm.jstree.js
@@ -5,13 +5,13 @@
 
 // Codes run both on normal page loads and when data is loaded by AJAX (or BigPipe!)
 // @See https://www.drupal.org/docs/8/api/javascript-api/javascript-api-overview
-(function($, Drupal) {
+(function($, Drupal, once) {
   Drupal.behaviors.hmJSTree = {
     attach: function(context, settings) {
-      $(".hm-jstree", context)
-        .once("jstreeBehavior")
-        .each(function() {
-          const treeContainer = $(this);
+      const hmJstree = once('hmJSTree', '.hm-jstree', context);
+      // Render all trees.
+      hmJstree.forEach(function(hmJstree) {
+          const treeContainer = $(hmJstree);
           const parentID = treeContainer.attr('parent-id');
           const searchTextID = (parentID) ? '#hm-jstree-search-' + parentID : '#hm-jstree-search';
           const optionsJson = treeContainer.attr("options");
@@ -251,4 +251,4 @@
     return modalConfirmationForm.dialog('open');
   }
 
-})(jQuery, Drupal);
+})(jQuery, Drupal, once);