Skip to content
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

refactor: [M3-8981] - User Preferences optimization with selector pattern (Part 1) #11386

Conversation

bnussman-akamai
Copy link
Member

Description 📝

  • Implements the "selector pattern" for our usePreferences hook
    • This allows us to "subscribe" to certain parts of the preferences object, which help us prevent unnecessary re-renders when an unrelated preference is updated 🏎️
    • See this post for a description of this React Query pattern

Note

This is just part 1, which introduces the pattern and uses it in a small number of places. I will follow up this PR with a part 2 (and maybe 3) to implement the pattern throughout the app.

Preview 📷

Important

No UI changes expected

How to test 🧪

  • Checkout this PR (or use a preview link)
  • Check the code
    • Verify the new pattern is intuitive
    • Check for code quality
  • To confirm this does not break anything
    • Verify the primary navigation collapsed state is correctly saved in user preferences
    • Verify the primary navigation collapsed state persists on related
Author Checklists

As an Author, to speed up the review process, I considered 🤔

👀 Doing a self review
❔ Our contribution guidelines
🤏 Splitting feature into small PRs
➕ Adding a changeset
🧪 Providing/improving test coverage
🔐 Removing all sensitive information from the code and PR description
🚩 Using a feature flag to protect the release
👣 Providing comprehensive reproduction steps
📑 Providing or updating our documentation
🕛 Scheduling a pair reviewing session
📱 Providing mobile support
♿ Providing accessibility support


  • I have read and considered all applicable items listed above.

As an Author, before moving this PR from Draft to Open, I confirmed ✅

  • All unit tests are passing
  • TypeScript compilation succeeded without errors
  • Code passes all linting rules

@bnussman-akamai bnussman-akamai added the React Query Relating to the transition to use React Query label Dec 9, 2024
@bnussman-akamai bnussman-akamai self-assigned this Dec 9, 2024
preferenceKey="linodes_group_by_tag"
preferenceOptions={[false, true]}
toggleCallbackFn={sendGroupByAnalytic}
>
{({
preference: linodesAreGrouped,
togglePreference: toggleGroupLinodes,
}: PreferenceToggleProps<boolean>) => {
Copy link
Member Author

@bnussman-akamai bnussman-akamai Dec 9, 2024

Choose a reason for hiding this comment

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

I improved the type-safety of PreferenceToggle. These explicit type annotations are no longer needed because the type is now properly inferred

@@ -14,9 +14,11 @@ export interface DismissedNotification {
label?: string;
}

export interface ManagerPreferences extends UserPreferences {
Copy link
Member Author

Choose a reason for hiding this comment

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

This extends was causing type-safety issues. It basically made ManagerPreferences extend Record<string, any>, which allowed any string key. Removing the extends allow us to be more strict.

avatarColor?: string;
backups_cta_dismissed?: boolean;
collapsedSideNavProductFamilies?: number[];
Copy link
Member Author

@bnussman-akamai bnussman-akamai Dec 9, 2024

Choose a reason for hiding this comment

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

These were types missing... Now that type-safety is better, developers will see type errors that will catch this

});

export const useMutatePreferences = (replace = false) => {
const { data: preferences } = usePreferences(!replace);
Copy link
Member Author

Choose a reason for hiding this comment

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

I removed this use of usePreferences and implemented mutationFn differently.

Using usePreferences here would cause any components that uses useMutatePreferences to re-render when preferences update. This change will eliminate that path to extra re-renders.

Comment on lines -256 to -258
const [collapsedAccordions, setCollapsedAccordions] = React.useState<
number[]
>(preferences?.collapsedSideNavProductFamilies ?? []);
Copy link
Member Author

Choose a reason for hiding this comment

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

We don't need to use extra state here. Because our user preferences optimistically update, we can essentially treat it as state.

Copy link
Member Author

Choose a reason for hiding this comment

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

Had to make some changes here to improve type-safety. See other comment in LinodesLanding.tsx

Comment on lines +96 to +98
const { data: collapsedSideNavPreference } = usePreferences(
(preferences) => preferences?.collapsedSideNavProductFamilies
);
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the new pattern in-use! ✨

Before: The primary nav would re-render when any preference was updated
After: The primary nav will only re-render when preferences.collapsedSideNavProductFamilies updates 🎉

Copy link
Contributor

@pmakode-akamai pmakode-akamai Dec 11, 2024

Choose a reason for hiding this comment

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

This could be unrelated, but I’m noticing that PrimaryNav re-renders when navigating to Create Image, while it doesn’t re-render when selecting any products from the Side Nav or any other Create {Product}.
Screenshot 2024-12-11 at 6 40 12 PM

understood - it's a Create Image, but is PrimaryNav supposed to get re-rendered in such cases??

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, that is unrelated. From my understanding, the primary nav will re-render when we change routes no matter what.

@bnussman-akamai bnussman-akamai marked this pull request as ready for review December 9, 2024 18:31
@bnussman-akamai bnussman-akamai requested a review from a team as a code owner December 9, 2024 18:31
@bnussman-akamai bnussman-akamai requested review from mjac0bs and pmakode-akamai and removed request for a team December 9, 2024 18:31
Copy link

github-actions bot commented Dec 10, 2024

Coverage Report:
Base Coverage: 86.78%
Current Coverage: 86.78%

Copy link
Contributor

@mjac0bs mjac0bs left a comment

Choose a reason for hiding this comment

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

Nice, this was a cool improvement to see demoed and it will be good to optimize preference-use throughout the app!

Confirmed:

  • The new pattern is easy to understand
  • No regressions with primary navigation and collapsed state is correctly saved in user preferences
  • Toggling other preferences does not rerender the primary navigation; only changes to the collapsed state
Screen.Recording.2024-12-11.at.9.11.52.AM.mov

@mjac0bs mjac0bs added the Add'tl Approval Needed Waiting on another approval! label Dec 11, 2024
@linode-gh-bot
Copy link
Collaborator

Cloud Manager UI test results

🎉 469 passing tests on test run #9 ↗︎

❌ Failing✅ Passing↪️ Skipped🕐 Duration
0 Failing469 Passing2 Skipped108m 25s

@pmakode-akamai pmakode-akamai added Approved Multiple approvals and ready to merge! and removed Add'tl Approval Needed Waiting on another approval! labels Dec 12, 2024
@bnussman-akamai bnussman-akamai merged commit abf05ca into linode:develop Dec 12, 2024
23 checks passed
Copy link

cypress bot commented Dec 12, 2024

Cloud Manager E2E    Run #6959

Run Properties:  status check passed Passed #6959  •  git commit abf05ca641: refactor: [M3-8981] - User Preferences optimization with selector pattern (Part ...
Project Cloud Manager E2E
Branch Review develop
Run status status check passed Passed #6959
Run duration 31m 11s
Commit git commit abf05ca641: refactor: [M3-8981] - User Preferences optimization with selector pattern (Part ...
Committer Banks Nussman
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 3
Tests that did not run due to a developer annotating a test with .skip  Pending 2
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 469
View all changes introduced in this branch ↗︎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Approved Multiple approvals and ready to merge! React Query Relating to the transition to use React Query
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants