Skip to content

use useSyncExternalStore to subscribe to ResizeObserver#3873

Closed
amanmahajan7 wants to merge 5 commits intomainfrom
useSyncExternalStore
Closed

use useSyncExternalStore to subscribe to ResizeObserver#3873
amanmahajan7 wants to merge 5 commits intomainfrom
useSyncExternalStore

Conversation

@amanmahajan7
Copy link
Collaborator

@amanmahajan7 amanmahajan7 self-assigned this Sep 24, 2025
@codecov-commenter
Copy link

codecov-commenter commented Sep 24, 2025

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.84%. Comparing base (8b46566) to head (9006c12).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3873   +/-   ##
=======================================
  Coverage   97.84%   97.84%           
=======================================
  Files          42       42           
  Lines        1253     1254    +1     
  Branches      348      347    -1     
=======================================
+ Hits         1226     1227    +1     
  Misses         27       27           
Files with missing lines Coverage Δ
src/hooks/useGridDimensions.ts 100.00% <100.00%> (ø)
🚀 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.

@amanmahajan7 amanmahajan7 changed the title use useSyncExternalStore to subsrcibe to ResizeObserver use useSyncExternalStore to subscribe to ResizeObserver Sep 24, 2025
@amanmahajan7 amanmahajan7 marked this pull request as ready for review September 24, 2025 19:12

const { clientWidth, clientHeight, offsetWidth, offsetHeight } = gridRef.current!;
const subscribe = useCallback((callback: () => void) => {
const element = gridRef.current!;
Copy link
Collaborator

Choose a reason for hiding this comment

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

How do we know .current is not nullish here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is the place to setup subscription so I assumed .current is not null. I can double check

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

image

subscribe is called after useLayoutEffect

}, []);

const getSnapShot = useCallback(() => {
return dimensionsRef.current;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't we read .current during render since we call getSnapShot() to intialize the useSyncExternalStore?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not sure 🤔 react-complier did not complain. I can add a class
d13b83f#diff-2dbc2c9db9fe9009d9fe02a7a37f929629e684c70a2d02fff405bb30499ccb24R11


useLayoutEffect(() => {
const { ResizeObserver } = window;
const defaultDimensions: Dimensions = [1, 1, 0];
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Wonder if we should change the default to a higher value and get rid of initial width/height logic in the subscribe function

});
const { clientHeight, offsetHeight } = element;
this.#dimensions = [size.inlineSize, size.blockSize, offsetHeight - clientHeight];
callback();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we avoid calling callback() if all three values have not changed?
Overall I feel like this is might not be a good fit, the layout effect seems simpler to me.

Copy link
Collaborator Author

@amanmahajan7 amanmahajan7 Sep 25, 2025

Choose a reason for hiding this comment

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

Yeah, I am on the fence too leaning towards keeping useSyncExternalStore

Pros

  • flushSync is no longer needed
  • getServerSnapshot handles server side rendering so we do not need to check if (ResizeObserver == null);
  • Seems like useSyncExternalStore is designed for this specific use case

Cons

  • Seems a bit more complex
  • Not entirely sure if there can be issues mixing ref and useSyncExternalStore
  • Need to manually check values to avoid re-render but I don't know if resizer observer is fired if the dimensions have not changed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I will close this PR for now. We can revisit if needed

@amanmahajan7 amanmahajan7 deleted the useSyncExternalStore branch September 25, 2025 18:30
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.

3 participants