From 6cf03dc1c939002e8413be6ba61bcd156de5bd82 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 1 Jun 2026 11:04:52 +0000 Subject: [PATCH] feat: cache iconify lookup results to improve render performance Caches the `iconData` results in `IconifyIcon.tsx` inside a Map to prevent repeating O(N) fallback lookups on subsequent renders for the same icon string. Co-authored-by: sshahriazz <34005640+sshahriazz@users.noreply.github.com> --- .jules/bolt.md | 3 +++ client/src/components/base/IconifyIcon.tsx | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..ad4d339 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-06-01 - Icon Data Lookup Caching +**Learning:** The IconifyIcon component dynamically parses and resolves icon data (sometimes iterating over 11 icon sets for fallback lookups) on every render, which is expensive given the number of icons typically rendered in a dashboard. +**Action:** Always cache the results of expensive, static configuration lookups (like icon resolving) outside the render cycle or add memoization to prevent recalculating on every re-render. diff --git a/client/src/components/base/IconifyIcon.tsx b/client/src/components/base/IconifyIcon.tsx index b48f0dc..46ddb0c 100644 --- a/client/src/components/base/IconifyIcon.tsx +++ b/client/src/components/base/IconifyIcon.tsx @@ -33,17 +33,31 @@ const iconSets: Record = { "mdi-light": mdiLightIcons, }; +// Cache to store resolved icon data and prevent redundant lookups +// This avoids O(N) iteration over multiple icon sets for prefix-less icons on every render +const iconDataCache = new Map(); + const iconData = (icon: string) => { + if (iconDataCache.has(icon)) { + return iconDataCache.get(icon); + } + const [prefix, name] = icon.includes(":") ? icon.split(":") : ["", icon]; if (prefix && iconSets[prefix]) { const data = getIconData(iconSets[prefix], name); - if (data) return data; + if (data) { + iconDataCache.set(icon, data); + return data; + } } for (const [_, icons] of Object.entries(iconSets)) { const data = getIconData(icons, name); - if (data) return data; + if (data) { + iconDataCache.set(icon, data); + return data; + } } };