Skip to content

Comments

Better memory optimizations#674

Merged
feruzm merged 8 commits intodevelopfrom
moreperform
Feb 23, 2026
Merged

Better memory optimizations#674
feruzm merged 8 commits intodevelopfrom
moreperform

Conversation

@feruzm
Copy link
Member

@feruzm feruzm commented Feb 23, 2026

Summary by CodeRabbit

  • New Features

    • Added pagination limits across feeds, including a short cap for promoted feed to reduce excessive loading.
  • Bug Fixes

    • Vote dialog buttons disabled while voting to prevent duplicate actions.
    • Embedded media and dynamic embeds now unmount cleanly to reduce memory leaks.
    • Modal keyboard and overflow handling improved for more reliable behavior.
  • Performance

    • Simplified market chart tooltip handling.
  • Chores

    • Version bump: SDK to 2.0.13, Wallets to 1.5.41.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

📝 Walkthrough

Walkthrough

Centralizes React root lifecycle for post-renderer enhancers (track/unmount roots and change enhancers to return Root[]), adds maxPages caps and tighter next-page guards across many infinite query options, and applies several UI/behavior fixes (tooltip/interval/key handling, timeout cleanup, disabling vote buttons, wallet token list tweak, version bumps).

Changes

Cohort / File(s) Summary
Post-renderer extensions
apps/web/src/features/post-renderer/components/extensions/author-link-extension.tsx, .../hive-operation-extension.tsx, .../hive-post-link-extension.tsx, .../tag-link-extension.tsx, .../three-speak-video-extension.tsx, .../twitter-extension.tsx, .../wave-like-post-extension.tsx, .../youtube-video-extension.tsx
Add rootsRef to track created React roots; unmount previous roots before creating new ones; push created Root into registry; add cleanup on effect/unmount to prevent leaks and stabilize callbacks.
Enhancer utilities (return roots)
apps/web/src/features/post-renderer/components/utils/hiveAuthorLinkEnhancer.tsx, .../hiveOperationEnhancer.tsx, .../hivePostLinkEnhancer.tsx, .../threespeakVideosEnhancer.tsx, .../twitterEnhancer.tsx, .../waveLinkEnhancer.tsx, .../youtubeVideosEnhancer.tsx
Change signatures to return Root[]; collect created React Root instances into a roots array and return it for later unmounting.
Setup & tests
apps/web/src/features/post-renderer/components/utils/setupPostEnhancements.ts, apps/web/src/features/post-renderer/components/utils/__tests__/setupPostEnhancements.spec.ts
Aggregate returned Root[] from enhancers into allRoots and unmount all roots in cleanup; update mocks and tests to reflect new return values, ordering, and cleanup expectations.
Infinite query caps & guards
packages/sdk/src/modules/.../queries/* (accounts, posts, wallet, notifications, search, hive-engine, communities, etc.)
Add maxPages: 5 to many infiniteQueryOptions; tighten some getNextPageParam implementations to return undefined on empty pages and add a guarded signature in specific queries (e.g., hive-engine) including getPreviousPageParam.
Market / intervals / modal UI
apps/web/src/app/_components/market-data/market.tsx, apps/web/src/app/decks/_components/header/deck-header-reloading.tsx, apps/web/src/features/ui/modal/index.tsx
Remove manual DOM tooltip and point-mouse wiring (rely on Highcharts tooltip); replace react-use interval/key hooks with native useEffect handlers and explicit cleanup; move body overflow handling into effect tied to show state.
Small fixes & controls
apps/web/src/app/(dynamicPages)/profile/[username]/layout.tsx, apps/web/src/app/decks/_components/columns/deck-threads-column.tsx, apps/web/src/features/shared/entry-vote-btn/entry-vote-dialog.tsx, packages/wallets/src/modules/wallets/queries/use-get-account-wallet-list-query.ts
Remove staleTime: Infinity from profile query; add retry timeout ref and cleanup; disable vote buttons while voting loads; prepend/deduplicate BASIC_TOKENS when visible portfolio tokens exist.
Changelogs & package bumps
packages/sdk/CHANGELOG.md, packages/sdk/package.json, packages/wallets/CHANGELOG.md, packages/wallets/package.json
Bump @ecency/sdk to 2.0.13 and wallets to 1.5.41; add changelog entries referencing memory optimizations.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hop through roots both old and new,

unmounting leaks with a careful chew.
Five pages capped — I count with delight,
intervals tamed and modals polite.
Memory tidy, the code sleeps tight. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.83% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Better memory optimizations' directly reflects the main focus of the changeset, which involves implementing memory management improvements across multiple components (React root tracking, timeout/interval cleanup, infinite query pagination caps, etc.).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch moreperform

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]

This comment was marked as resolved.

@feruzm feruzm added the patch Bug fixes and patches (1.0.0 → 1.0.1), add this only if any packages/ have patch changes in PR label Feb 23, 2026
coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/src/app/_components/market-data/market.tsx (1)

65-71: ⚠️ Potential issue | 🟠 Major

Broken tooltip: arrow function defeats Highcharts' this-based formatter context.

Highcharts invokes tooltip.formatter with this bound to the hovered Point instance (Highcharts v12+; for shared/split tooltips, this.points is also available). Arrow functions capture the lexical this and ignore .call() rebinding, so no context is received.

The current code uses an arrow function expecting a { chart } parameter, but Highcharts passes no explicit arguments. At runtime, chart is undefined, and chart.hoverPoint.options.x immediately throws TypeError: Cannot read property 'hoverPoint' of undefined. The as any cast masks this type error from the compiler.

Replace with a regular function to access this.x and this.y directly from the Point context:

🛠️ Proposed fix
-    formatter: (({ chart }: any) => {
-      let date = dayjs(chart.hoverPoint.options.x).calendar();
-      let rate = chart.hoverPoint.options.y;
-      return `<div><div>${i18next.t("g.when")}: <b>${date}</b></div><div>${i18next.t(
-        "g.price"
-      )}:<b>${rate.toFixed(3)}</b></div></div>`;
-    }) as any,
+    formatter: function (this: Highcharts.TooltipFormatterContextObject) {
+      const date = dayjs(this.x).calendar();
+      const rate = this.y as number;
+      return `<div><div>${i18next.t("g.when")}: <b>${date}</b></div><div>${i18next.t(
+        "g.price"
+      )}:<b>${rate.toFixed(3)}</b></div></div>`;
+    },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/_components/market-data/market.tsx` around lines 65 - 71,
The tooltip.formatter is currently an arrow function (formatter) that expects a
{ chart } param, which breaks Highcharts' this-based formatter context; change
formatter to a regular function so it can use the Point context (this) directly:
read date from dayjs(this.x).calendar() and rate from this.y (then call
toFixed(3)) and keep i18next.t("g.when") / i18next.t("g.price") for labels;
remove the ({ chart }: any) parameter and the arrow so Highcharts'
.call(thisPoint) works and the TypeError disappears.
♻️ Duplicate comments (1)
apps/web/src/features/post-renderer/components/extensions/hive-operation-extension.tsx (1)

110-113: LGTM — for...of cleanup correctly unmounts all tracked roots.

The past Biome lint error (forEach returning a value) is resolved. The for...of loop avoids the implicit return, and setting rootsRef.current = [] ensures the accumulator is cleared before the next effect run.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/web/src/features/post-renderer/components/extensions/hive-operation-extension.tsx`
around lines 110 - 113, The cleanup function is already fixed: replace any prior
use of Array.prototype.forEach that returned a value with a for...of loop that
calls r.unmount() for each tracked root and then reset rootsRef.current = [];
ensure the cleanup return in the effect uses the for...of iteration over
rootsRef.current and the explicit rootsRef.current = [] reset so all roots (via
their unmount method) are unmounted and the accumulator cleared.
🧹 Nitpick comments (1)
apps/web/src/features/post-renderer/components/extensions/hive-operation-extension.tsx (1)

95-99: Consider capturing the listener reference for explicit removal during cleanup.

container.addEventListener("click", () => onClickRef.current?.(op)) adds an anonymous listener that can never be removed. Since containerRef is a stable RefObject the effect effectively runs once, so in the normal unmount path the entire parent DOM subtree is torn down and GC handles it — but if the effect ever re-runs (e.g., a different containerRef object is passed), old containers remain in the DOM with zombie click handlers.

Capturing the handler and removing it in the cleanup would make the lifecycle explicit and guard against that edge case:

🔧 Proposed refactor
-                    container.addEventListener("click", () => onClickRef.current?.(op));
+                    const clickHandler = () => onClickRef.current?.(op);
+                    container.addEventListener("click", clickHandler);

Then store { root, container, clickHandler } (or a parallel handlersRef) so the cleanup can call container.removeEventListener("click", clickHandler) before r.unmount().

Alternatively, keep the approach but add a reset at the start of the effect body so stale containers are removed from the DOM before re-processing:

     useEffect(() => {
+        for (const r of rootsRef.current) { r.unmount(); }
+        rootsRef.current = [];
         Array.from(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/web/src/features/post-renderer/components/extensions/hive-operation-extension.tsx`
around lines 95 - 99, The click listener added via
container.addEventListener("click", () => onClickRef.current?.(op)) uses an
anonymous function that cannot be removed; change the effect to create a named
clickHandler (e.g., const clickHandler = () => onClickRef.current?.(op)), attach
it with container.addEventListener("click", clickHandler), and store the triple
{ root, container, clickHandler } (or maintain a parallel handlersRef) instead
of only pushing root to rootsRef; in the effect cleanup iterate these stored
entries and call container.removeEventListener("click", clickHandler) before
calling root.unmount() so old containers cannot retain zombie handlers if the
effect re-runs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@apps/web/src/app/_components/market-data/market.tsx`:
- Around line 65-71: The tooltip.formatter is currently an arrow function
(formatter) that expects a { chart } param, which breaks Highcharts' this-based
formatter context; change formatter to a regular function so it can use the
Point context (this) directly: read date from dayjs(this.x).calendar() and rate
from this.y (then call toFixed(3)) and keep i18next.t("g.when") /
i18next.t("g.price") for labels; remove the ({ chart }: any) parameter and the
arrow so Highcharts' .call(thisPoint) works and the TypeError disappears.

---

Duplicate comments:
In
`@apps/web/src/features/post-renderer/components/extensions/hive-operation-extension.tsx`:
- Around line 110-113: The cleanup function is already fixed: replace any prior
use of Array.prototype.forEach that returned a value with a for...of loop that
calls r.unmount() for each tracked root and then reset rootsRef.current = [];
ensure the cleanup return in the effect uses the for...of iteration over
rootsRef.current and the explicit rootsRef.current = [] reset so all roots (via
their unmount method) are unmounted and the accumulator cleared.

---

Nitpick comments:
In
`@apps/web/src/features/post-renderer/components/extensions/hive-operation-extension.tsx`:
- Around line 95-99: The click listener added via
container.addEventListener("click", () => onClickRef.current?.(op)) uses an
anonymous function that cannot be removed; change the effect to create a named
clickHandler (e.g., const clickHandler = () => onClickRef.current?.(op)), attach
it with container.addEventListener("click", clickHandler), and store the triple
{ root, container, clickHandler } (or maintain a parallel handlersRef) instead
of only pushing root to rootsRef; in the effect cleanup iterate these stored
entries and call container.removeEventListener("click", clickHandler) before
calling root.unmount() so old containers cannot retain zombie handlers if the
effect re-runs.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b325b10 and 9ac9420.

⛔ Files ignored due to path filters (6)
  • packages/sdk/dist/browser/index.js is excluded by !**/dist/**
  • packages/sdk/dist/browser/index.js.map is excluded by !**/dist/**, !**/*.map
  • packages/sdk/dist/node/index.cjs is excluded by !**/dist/**
  • packages/sdk/dist/node/index.cjs.map is excluded by !**/dist/**, !**/*.map
  • packages/sdk/dist/node/index.mjs is excluded by !**/dist/**
  • packages/sdk/dist/node/index.mjs.map is excluded by !**/dist/**, !**/*.map
📒 Files selected for processing (4)
  • apps/web/src/app/_components/market-data/market.tsx
  • apps/web/src/features/post-renderer/components/extensions/hive-operation-extension.tsx
  • apps/web/src/features/post-renderer/components/extensions/youtube-video-extension.tsx
  • packages/sdk/src/modules/hive-engine/queries/get-hive-engine-token-transactions-query-options.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/features/post-renderer/components/extensions/youtube-video-extension.tsx

@feruzm feruzm merged commit 175e496 into develop Feb 23, 2026
1 check passed
@feruzm feruzm deleted the moreperform branch February 23, 2026 19:50
@coderabbitai coderabbitai bot mentioned this pull request Feb 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

patch Bug fixes and patches (1.0.0 → 1.0.1), add this only if any packages/ have patch changes in PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant