Skip to content

⚡ Bolt: Prevent O(N) re-renders in high-frequency WebSocket components#146

Draft
primoscope wants to merge 1 commit intomainfrom
bolt-optimize-react-renders-17722708389685146381
Draft

⚡ Bolt: Prevent O(N) re-renders in high-frequency WebSocket components#146
primoscope wants to merge 1 commit intomainfrom
bolt-optimize-react-renders-17722708389685146381

Conversation

@primoscope
Copy link
Copy Markdown
Owner

💡 What:
Extracted the list item rendering logic in ProgressPanel (for downloads) and LogPanel (for logs) into their own components (DownloadItem and LogItem), wrapped them in React.memo, and provided stable keys (by assigning a unique client-side id to log messages). Static helper functions were also moved out of the render bodies.

🎯 Why:
Because these components subscribe to high-frequency WebSocket streams, updating a single item in the downloads or appending a single item to the logs array would previously cause the entire array of inline elements to re-render in React. This is an O(N) rendering bottleneck that degrades UI performance as the list sizes grow.

📊 Impact:
Prevents O(N) re-renders across the dashboard when a new log arrives or a download's progress ticks. This significantly reduces main-thread blocking and memory churn, keeping the UI smooth even with dozens of active downloads and thousands of log entries streaming in.

🔬 Measurement:
Use the React Profiler to record interactions while downloads are active. You will see that only the individual DownloadItem components whose progress actually changed are re-rendering, rather than the entire list. For logs, only the newly appended LogItem mounts; previously rendered logs will not re-render.


PR created automatically by Jules for task 17722708389685146381 started by @dzp5103

- Extract inline list item render logic in `ProgressPanel` and `LogPanel` into separate `DownloadItem` and `LogItem` components.
- Wrap extracted components in `React.memo` to prevent unnecessary re-renders.
- Use a custom equality function for `DownloadItem` to perform shallow comparison of primitive fields safely.
- Add an `id` field to `LogMessage` and generate a stable client-side unique ID upon receiving log messages, using this ID as the React `key` instead of the array index.
- Move static formatting and coloring functions (`formatSpeed`, `formatETA`, `getStatusColor`, `getLogColor`) outside of component bodies to avoid recreating them on every render.
- Added explanatory inline comments.

Co-authored-by: dzp5103 <214723817+dzp5103@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

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.

1 participant