Skip to content

⚡ Bolt: Optimize array filtering with useMemo in UI components#467

Open
Doezer wants to merge 1 commit intomainfrom
bolt-usememo-filters-9353282455376142549
Open

⚡ Bolt: Optimize array filtering with useMemo in UI components#467
Doezer wants to merge 1 commit intomainfrom
bolt-usememo-filters-9353282455376142549

Conversation

@Doezer
Copy link
Owner

@Doezer Doezer commented Mar 18, 2026

💡 What:
Wrapped several games.filter(...) array operations inside useMemo hooks in key components (AppSidebar, library.tsx, and wishlist.tsx). Added the necessary imports as well.

🎯 Why:
Previously, these components were re-evaluating the games array filtering on every render. Because these are frequent or top-level components (e.g., AppSidebar handles polling for downloads), this unmemoized O(n) operation could cause performance jank and slow down the app as the user's game library grows.

📊 Impact:
Reduces main thread blocking by avoiding O(n) recalculations on every render. The lists will now only be recalculated when the underlying games array from the query cache actually changes.

🔬 Measurement:
Run npm run lint and npm test (both pass) to verify that the logic remains correct. You can use React Developer Tools Profiler to observe that the filter functions are no longer re-invoked on state changes unrelated to games.


PR created automatically by Jules for task 9353282455376142549 started by @Doezer

…enders

Wrapped `games.filter(...)` operations in `library.tsx`, `wishlist.tsx`, and `AppSidebar.tsx` with `useMemo` hooks. This prevents O(n) array recalculations on every component render, improving performance and avoiding UI jank.

Co-authored-by: Doezer <11655673+Doezer@users.noreply.github.com>
@google-labs-jules
Copy link
Contributor

👋 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.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves application performance by introducing memoization to frequently accessed and re-rendered UI components. By wrapping expensive array filtering operations in useMemo, the application avoids unnecessary recalculations, especially as the user's game library grows, leading to a smoother user experience and reduced main thread blocking.

Highlights

  • Performance Optimization: Wrapped several array filtering operations (games.filter(...)) within useMemo hooks in key UI components to prevent redundant calculations on every render.
  • Affected Components: Applied memoization to AppSidebar, library.tsx, and wishlist.tsx components, which previously re-evaluated game list filtering frequently.
  • Dependency Management: Added useMemo imports where necessary to support the new memoization logic.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@sonarqubecloud
Copy link

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request correctly introduces useMemo to optimize array filtering in several components, preventing unnecessary recalculations on re-renders. This is a good performance improvement. My review includes a suggestion for AppSidebar.tsx to further optimize the calculation by combining two separate array iterations into a single pass using reduce, which will make it even more efficient.

Comment on lines +124 to +132
const libraryCount = useMemo(() => {
return games.filter((g) =>
["owned", "completed", "downloading"].includes(g.status)
).length;
}, [games]);

const wishlistCount = useMemo(() => {
return games.filter((g) => g.status === "wanted").length;
}, [games]);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

While wrapping these calculations in useMemo is a great optimization, we can make this even more efficient. Currently, you are iterating over the games array twice (once for libraryCount and once for wishlistCount). You can combine these into a single iteration using Array.prototype.reduce to calculate both counts in one pass. This will be more performant, especially as the number of games grows.

  const { libraryCount, wishlistCount } = useMemo(() => {
    return games.reduce(
      (counts, g) => {
        if (["owned", "completed", "downloading"].includes(g.status)) {
          counts.libraryCount++;
        } else if (g.status === "wanted") {
          counts.wishlistCount++;
        }
        return counts;
      },
      { libraryCount: 0, wishlistCount: 0 }
    );
  }, [games]);
References
  1. To optimize array processing, combine multiple iterations into a single pass where possible, for instance by using reduce after initial filtering and sorting, to avoid redundant traversals.

@codecov
Copy link

codecov bot commented Mar 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

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