Skip to content

ENG-1642 Discourse context overlay gets re-triggered every hover in a query block when view is render#989

Merged
mdroidian merged 4 commits into
mainfrom
eng-1642-discourse-context-overlay-gets-re-triggered-every-hover-in-a
May 7, 2026
Merged

ENG-1642 Discourse context overlay gets re-triggered every hover in a query block when view is render#989
mdroidian merged 4 commits into
mainfrom
eng-1642-discourse-context-overlay-gets-re-triggered-every-hover-in-a

Conversation

@maparent

@maparent maparent commented Apr 30, 2026

Copy link
Copy Markdown
Collaborator

https://linear.app/discourse-graphs/issue/ENG-1642/discourse-context-overlay-gets-re-triggered-every-hover-in-a-query

https://www.loom.com/share/b8b7fcfe79334491946a95b2f0530103

Diagnostic: The RenderRoamBlockString inside CellRender seems to use useEffects to clear and re-render its contents. So when React asks CellRender to recreate the virtual DOM, in particular on every mouseEnter/mouseLeave to the resultsTable, the effects re-run, and the content is re-rendered from scratch. The solution provided by Claude was to apply React.memo on the CellRender,ResultRow,ResultTable stack, so these are not re-rendered when the props are the same. We had to make sure each prop was wrapped in either useMemo or useCallback.

Note: This induced a lot of whitespace changes. The only effective changes are introducing React.memo on those three components.


Open in Devin Review

Summary by CodeRabbit

  • Refactor
    • Optimized results table component rendering for improved performance and responsiveness.

@linear-code

linear-code Bot commented Apr 30, 2026

Copy link
Copy Markdown

@supabase

supabase Bot commented Apr 30, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

@maparent maparent requested a review from mdroidian May 1, 2026 01:18
@mdroidian

Copy link
Copy Markdown
Member

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@mdroidian has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 51 minutes and 59 seconds before requesting another review.

To continue reviewing without waiting, purchase usage credits in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ca640d03-6770-44c7-be6b-3dc37ee53849

📥 Commits

Reviewing files that changed from the base of the PR and between 82749a3 and a83a728.

📒 Files selected for processing (3)
  • apps/roam/src/components/results-view/ResultsTable.tsx
  • apps/roam/src/components/results-view/ResultsView.tsx
  • apps/roam/src/styles/styles.css
📝 Walkthrough

Walkthrough

Memoization optimization applied to ResultsTable.tsx. Three React components—CellRender, ResultRow, and ResultsTable—are wrapped with memo() to prevent unnecessary re-renders. CellRender is no longer exported; internal render logic remains unchanged.

Changes

Component Memoization

Layer / File(s) Summary
Import Updates
apps/roam/src/components/results-view/ResultsTable.tsx
memo is added to the React import statement.
Component Wrapping
apps/roam/src/components/results-view/ResultsTable.tsx
CellRender and ResultRow are wrapped with memo(), and displayName is set on both. ResultsTable default export is wrapped with memo().
Export Changes
apps/roam/src/components/results-view/ResultsTable.tsx
Named export of CellRender is removed; it becomes an internal memoized constant. Default export changes from ResultsTable to memo(ResultsTable).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the bug being fixed (discourse context overlay re-triggering on hover) and aligns with the PR's objective to prevent unnecessary re-renders by memoizing components.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


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.

@mdroidian

Copy link
Copy Markdown
Member

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 3, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/roam/src/components/results-view/ResultsTable.tsx (1)

164-175: ⚡ Quick win

Add explicit return types to the new memoized component functions.

Both newly changed component callbacks are missing explicit return types. Please annotate them (e.g., : JSX.Element) to match repo TS rules.

Suggested patch
+type CellRenderProps = { content: string; uid: string };
 const CellRender = memo(
-  ({ content, uid }: { content: string; uid: string }) => {
+  ({ content, uid }: CellRenderProps): JSX.Element => {
     const isPage = !!getPageTitleByPageUid(uid);
     const displayString = isPage ? `[[${content}]]` : content;

     return (
       <span className="roamjs-query-link-cell">
         <RenderRoamBlockString string={displayString} />
       </span>
     );
   },
 );
@@
 const ResultRow = memo(
   ({
@@
-  }: ResultRowProps) => {
+  }: ResultRowProps): JSX.Element => {

As per coding guidelines, "Use explicit return types for functions in TypeScript".

Also applies to: 190-421

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

In `@apps/roam/src/components/results-view/ResultsTable.tsx` around lines 164 -
175, The memoized component callbacks are missing explicit return types; update
the CellRender memo callback (and the other memoized callback in the same file)
to annotate their function signatures with an explicit return type like ":
JSX.Element" (e.g., change "({ content, uid }: { content: string; uid: string })
=> { ... }" to "({ content, uid }: { content: string; uid: string }):
JSX.Element => { ... }"); ensure React/JSX types are available in scope if
needed and keep the memo wrapper (CellRender) unchanged otherwise.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/roam/src/components/results-view/ResultsTable.tsx`:
- Around line 164-175: The memoized component callbacks are missing explicit
return types; update the CellRender memo callback (and the other memoized
callback in the same file) to annotate their function signatures with an
explicit return type like ": JSX.Element" (e.g., change "({ content, uid }: {
content: string; uid: string }) => { ... }" to "({ content, uid }: { content:
string; uid: string }): JSX.Element => { ... }"); ensure React/JSX types are
available in scope if needed and keep the memo wrapper (CellRender) unchanged
otherwise.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 33b3ed15-5a98-4915-84b9-e9065866fd3a

📥 Commits

Reviewing files that changed from the base of the PR and between 82749a3 and b0f4cf6.

📒 Files selected for processing (1)
  • apps/roam/src/components/results-view/ResultsTable.tsx

maparent commented May 5, 2026

Copy link
Copy Markdown
Collaborator Author

@mdroidian Just checking: I think you wanted me to look into why embeddings were not affected, correct? Or did you intend to do it as part of review?

@mdroidian

Copy link
Copy Markdown
Member

@mdroidian Just checking: I think you wanted me to look into why embeddings were not affected, correct? Or did you intend to do it as part of review?

I can take a look. Memoizing ResultRow and especially all of ResultsTable seems like overkill when View Type > embed doesn't have this same problem. I think it's worth investigating to see if we can identify a more focused fix.

@mdroidian mdroidian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the memoization fix is treating the symptom rather than the root cause.

The overlay is being retriggered because hovering the query results currently updates React state in ResultsView (revealMenuIcons), which rerenders the results table. In render view, that means Roam’s BlockString output can be recreated, which causes the page-ref observer / discourse overlay path to run again.

Memoizing ResultsTable/ResultRow can suppress that rerender in this case, but it is a broad workaround around a hover-only UI concern. It also risks hiding future legitimate updates because the whole table/row rendering path becomes dependent on memo boundaries.

A narrower fix is to remove the hover state entirely and let CSS reveal the query controls on hover. That keeps the same UI behavior without causing React to rerender the query results table every time the mouse enters or leaves the query block.

I have shown that here:
#1006
https://www.loom.com/share/764c12c0caa948d2816c5f9c1e5ea74d

maparent commented May 7, 2026

Copy link
Copy Markdown
Collaborator Author

That makes sense. Since you did write the fix, do you want to take this over?

- Removed state management for revealMenuIcons and associated mouse event handlers.
- Introduced a new className for menu icons to control visibility based on interface settings and hover state.
- Updated CSS to manage menu icon display logic, enhancing user experience by streamlining the interface.

This change improves the clarity and maintainability of the ResultsView component.
@graphite-app

This comment was marked as resolved.

@mdroidian

Copy link
Copy Markdown
Member

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@mdroidian mdroidian merged commit e52fddb into main May 7, 2026
9 checks passed
@mdroidian mdroidian deleted the eng-1642-discourse-context-overlay-gets-re-triggered-every-hover-in-a branch May 7, 2026 04:27
trangdoan982 pushed a commit that referenced this pull request May 11, 2026
… query block when view is render (#989)

* ENG-1642 Memoize results table to avoid redraws

* spurious includes

* Refactor ResultsView component to simplify menu icon visibility (#1006)

- Removed state management for revealMenuIcons and associated mouse event handlers.
- Introduced a new className for menu icons to control visibility based on interface settings and hover state.
- Updated CSS to manage menu icon display logic, enhancing user experience by streamlining the interface.

This change improves the clarity and maintainability of the ResultsView component.

* remove memo

---------

Co-authored-by: Michael Gartner <mclicks@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants