Skip to content

Conversation

Parship999
Copy link
Contributor

Which problem is this PR solving?

Description of the changes

  • Removed: react-window
  • Added: @tanstack/react-virtual
  • Migration: complete functional replacement

How was this change tested?

  • unit tests

Checklist

Signed-off-by: Parship Chowdhury <i.am.parship@gmail.com>
@Parship999 Parship999 requested a review from a team as a code owner September 8, 2025 17:03
@Parship999 Parship999 requested review from pavolloffay and removed request for a team September 8, 2025 17:03
Copy link
Contributor

graphite-app bot commented Sep 8, 2025

How to use the Graphite Merge Queue

Add the label merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

Comment on lines +63 to +68
useEffect(() => {
if (hasMountedRef.current && inputRef.current) {
inputRef.current.focus();
}
}
const checked = Boolean(checkedCount) && checkedCount === filtered.length;
const title = `Click to ${checked ? 'unselect' : 'select'} all ${
filtered.length < options.length ? 'filtered ' : ''
}options`;
hasMountedRef.current = true;
});
Copy link
Contributor

Choose a reason for hiding this comment

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

The useEffect hook is missing a dependency array, which means it will run after every render. This creates a potential focus management issue where the input could be focused unexpectedly during re-renders triggered by state changes or other effects.

Consider adding an appropriate dependency array to control when this effect runs:

useEffect(() => {
  if (hasMountedRef.current && inputRef.current) {
    inputRef.current.focus();
  }
  hasMountedRef.current = true;
}, []); // Empty dependency array to run only on mount

Alternatively, if the intent is to focus only when specific conditions change, include those conditions in the dependency array to make the behavior more predictable and avoid unexpected focus shifts during user interaction.

Suggested change
useEffect(() => {
if (hasMountedRef.current && inputRef.current) {
inputRef.current.focus();
}
}
const checked = Boolean(checkedCount) && checkedCount === filtered.length;
const title = `Click to ${checked ? 'unselect' : 'select'} all ${
filtered.length < options.length ? 'filtered ' : ''
}options`;
hasMountedRef.current = true;
});
useEffect(() => {
if (hasMountedRef.current && inputRef.current) {
inputRef.current.focus();
}
hasMountedRef.current = true;
}, []);

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Copy link

codecov bot commented Sep 8, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.16%. Comparing base (d7389f7) to head (4f71e39).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3070      +/-   ##
==========================================
+ Coverage   98.13%   98.16%   +0.03%     
==========================================
  Files         257      257              
  Lines        8004     8085      +81     
  Branches     2092     2118      +26     
==========================================
+ Hits         7855     7937      +82     
+ Misses        149      148       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Signed-off-by: Parship Chowdhury <i.am.parship@gmail.com>
Comment on lines +182 to +188
const onListScrolled = useMemo(
() =>
_debounce(() => {
setFocusedIndex(null);
}, 80),
[]
);
Copy link
Contributor

Choose a reason for hiding this comment

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

The useMemo with an empty dependency array creates a new debounced function on mount, but this approach doesn't properly clean up the debounced function when the component unmounts. This can lead to memory leaks as the debounced function may continue to hold references to component state.

Consider using useCallback with a cleanup function in useEffect:

const onListScrolled = useCallback(
  _debounce(() => {
    setFocusedIndex(null);
  }, 80),
  []
);

useEffect(() => {
  return () => {
    // Clean up the debounced function on unmount
    onListScrolled.cancel();
  };
}, [onListScrolled]);

This ensures the debounced function is properly cleaned up when the component unmounts, preventing potential memory leaks and race conditions.

Suggested change
const onListScrolled = useMemo(
() =>
_debounce(() => {
setFocusedIndex(null);
}, 80),
[]
);
const onListScrolled = useCallback(
_debounce(() => {
setFocusedIndex(null);
}, 80),
[]
);
useEffect(() => {
return () => {
// Clean up the debounced function on unmount
onListScrolled.cancel();
};
}, [onListScrolled]);

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Signed-off-by: Parship Chowdhury <i.am.parship@gmail.com>
@Parship999
Copy link
Contributor Author

bvaughn/react-window#302
bvaughn/react-window#802.
So acc to my investigation: the main issue is that react-window does not officially support react 19 yet.

@yurishkuro
Copy link
Member

https://github.com/tanstack looks like a reasonable choice

@Parship999 Parship999 marked this pull request as draft September 13, 2025 16:59
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.

[deps]: Update or replace dependency react-window
2 participants