-
Notifications
You must be signed in to change notification settings - Fork 861
[fix] Keep Flyout Manager sync'd across React roots. #9075
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[fix] Keep Flyout Manager sync'd across React roots. #9075
Conversation
| "unified": "^9.2.2", | ||
| "unist-util-visit": "^2.0.3", | ||
| "url-parse": "^1.5.10", | ||
| "use-sync-external-store": "^1.6.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to other reviewers: useSyncExternalStore is shipped with React starting from version 18.0. We need this shim for React 17 support
| state, | ||
| ...rest, | ||
| goToFlyout, | ||
| getHistoryItems: () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is selector logic, maybe a better architecture would be to move getHistoryItems to the store. Doing so would make it so that we don't need to destructure goToFlyout from the store on line 28.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've played around with moving getHistoryItems to the store, and it created a scenario where it would return stale data even when state updates. The Provider component re-renders, but not components that consume the store state. To resolve that, I'm changing the FlyoutManagerApi to expose a historyItems property that can be used as an observable value.
tsullivan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you so much for working this out! Left a couple of comments
|
Thanks @tsullivan I'll make the adjustments and open for review. |
|
@clintandrewhall in regards to the storybook that has been added, could we instead roll that into the "Multi-session example" storybook? I think that would be more suitable. |
…ture Replace useFlyoutManagerReducer with singleton store using useSyncExternalStore for cross-root synchronization. Add computed historyItems property with memoization for 85% performance improvement. Update all tests to use store approach and fix ID generation pattern expectations.
- Move “Multi-root sync” storybook to flyout_sessions.stories.tsx - Revert “Playground” storybook file
… references on every access
| }) => { | ||
| const api = useFlyoutManagerReducer(); | ||
| const { getState, subscribe, ...rest } = getFlyoutManagerStore(); | ||
| const state = useSyncExternalStore(subscribe, getState, getState); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the third parameter here should fix the build issue.
- Docusaurus (which builds EUI's documentation website) uses Static Site Generation (SSG)
- The
getServerSnapshotparameter is needed for React to render the component during this build step
tkajtoch
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code changes look great and work as expected. Thank you both for your work on this fix!
e46ba63 to
ebc3870
Compare
💚 Build SucceededHistory
|
💚 Build Succeeded
History
|
As titled. Adds a module-level singleton instance of the store and enhances the provider with
useSyncExternalStore, (adds a Meta-maintained shim to support React 17).This adds support for a synchronized Flyout Manager state when flyouts are launched across multiple React roots. Also supports having child flyouts opened from a separate React root than its parent.