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

upcoming: [DI-20360] - Updated preferences logic to remove flickering issue #10853

Merged

Conversation

nikhagra-akamai
Copy link
Contributor

@nikhagra-akamai nikhagra-akamai commented Aug 29, 2024

Description 📝

Changed the current implementation of UserPreference to avoid flickering issue in widget component

Changes 🔄

List any change relevant to the reviewer.

  1. Created a custom hook useAclpPreference in UserPreference.ts file
  2. Removed useEffect from CloudPulseWidget component
  3. Updated CloudPulseDashboard component to use default time_granularity if preference is not present

Target release date 🗓️

5th September 2024

Preview 📷

Include a screenshot or screen recording of the change

💡 Use <video src="" /> tag when including recordings in table.

Before After
Screenshot 2024-08-29 at 6 58 16 PM Screenshot 2024-08-29 at 6 58 47 PM
Screenshot 2024-08-29 at 6 58 57 PM Screenshot 2024-08-29 at 6 58 05 PM

How to test 🧪

  1. Switch to mock user as APIs are not live.
  2. Change global filters value & you can check if UI is flickering or not because of component re-renderings

As an Author I have considered 🤔

Check all that apply

  • 👀 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

@nikhagra-akamai nikhagra-akamai requested a review from a team as a code owner August 29, 2024 13:31
@nikhagra-akamai nikhagra-akamai requested review from bnussman-akamai and abailly-akamai and removed request for a team August 29, 2024 13:31
@nikhagra-akamai nikhagra-akamai marked this pull request as draft August 29, 2024 14:09
@nikhagra-akamai nikhagra-akamai marked this pull request as ready for review September 2, 2024 13:10
@nikhagra-akamai
Copy link
Contributor Author

Hi @jaalah-akamai / @bnussman-akamai / @abailly-akamai, I've updated the logics to reduce re-renderings. Please start reviewing the PR

Copy link

github-actions bot commented Sep 3, 2024

Coverage Report:
Base Coverage: 86.98%
Current Coverage: 86.98%

Copy link
Member

@bnussman-akamai bnussman-akamai left a comment

Choose a reason for hiding this comment

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

My two main pieces of feedback are:

  • useRef in UserPreference.ts should not be necessary. If it is necessary to make CloudPulse work, is indicative of a larger issues.
  • I see preferences and updatePreferences getting passed down via props to a ton of components. Rather than passing it down via props, you can just use the hooks in the component itself. Doing this will allow us to minimize the number of props and could help with the number of components re-rendering

@nikhagra-akamai
Copy link
Contributor Author

nikhagra-akamai commented Sep 4, 2024

My two main pieces of feedback are:

  • useRef in UserPreference.ts should not be necessary. If it is necessary to make CloudPulse work, is indicative of a larger issues.
  • I see preferences and updatePreferences getting passed down via props to a ton of components. Rather than passing it down via props, you can just use the hooks in the component itself. Doing this will allow us to minimize the number of props and could help with the number of components re-rendering

Yes refs are needed because we are passing preference when the component initially renders and then we only allow component to render externally when major props change. If we remove refs then we have to call user preference in every component instead of props in this way we can completely remove internal state variables but my only concern is re-renderings will increase compare to what it is now. And if number of filters increased then it may cause impact application performance

@jaalah-akamai
Copy link
Contributor

As discussed async - The plan is to move forward with removing the preferences and updatePreferences from being passed down via props and call the hook directly in the components that use preferences where it makes sense. For the components that only rely on preferences on initial load, we can just pass down the specific value they need instead of the entire preferences object which should help with re-rendering (since they're memoized components).

@nikhagra-akamai
Copy link
Contributor Author

@cpathipa I've modulaized the code as per the suggestions please re-review

@nikhagra-akamai
Copy link
Contributor Author

@abailly-akamai / @hkhalil-akamai I've updated all the changes and test cases as well. Please review it once & approve if all good

@@ -123,5 +117,6 @@ export const CloudPulseDashboardSelect = React.memo(
value={selectedDashboard ?? null} // Undefined is not allowed for uncontrolled component
/>
);
}
},
() => true
Copy link
Member

Choose a reason for hiding this comment

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

Should this be here? useMemo should only be used if necessary. Is it necessary here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes this compare function is not required, I've removed it from few components. Though useMemo will required as we don't want component to re-render if some other preference value changes

};
return {
isLoading,
preferences: { ...(preferences?.aclpPreference ?? {}) },
Copy link
Member

Choose a reason for hiding this comment

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

What is going on here? Can this be

Suggested change
preferences: { ...(preferences?.aclpPreference ?? {}) },
preferences: preferences?.aclpPreference ?? {},

Comment on lines 168 to 171
export const arrayDeepEqual = (
oldValue: number[] | string[],
newValue: number[] | string[]
): boolean => {
Copy link
Member

Choose a reason for hiding this comment

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

Utils like this need to be unit tested.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've removed this method, it is not required

Comment on lines 80 to 116
(oldProps: DashboardProp, newProps: DashboardProp) => {
if (oldProps.dashboard?.id !== newProps.dashboard?.id) {
return false;
}

if (
oldProps.timeDuration?.unit !== newProps.timeDuration?.unit ||
oldProps.timeDuration?.value !== newProps.timeDuration?.value
) {
return false;
}

const oldKeys = Object.keys(oldProps.filterValue);
const newKeys = Object.keys(newProps.filterValue);

if (oldKeys.length !== newKeys.length) {
return false;
}

for (const key of oldKeys) {
const oldValue = oldProps.filterValue[key];
const newValue = newProps.filterValue[key];

if (
Array.isArray(oldValue) &&
Array.isArray(newValue) &&
!arrayDeepEqual(oldValue, newValue)
) {
return false;
}

if (oldValue !== newValue) {
return false;
}
}
return true;
}
Copy link
Member

Choose a reason for hiding this comment

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

I'm not saying this is wrong, but in my time writing React, I've never had to be this granular with memoization. I feel like things shouldn't have to be like this.

I also wonder how the React 19 compiler could affect stuff like this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just checked this compare function will not be required, only surrounded with memo works

@nikhagra-akamai
Copy link
Contributor Author

@bnussman-akamai thanks for suggestions. Alot of not required code I've removed and pushed.

@nikhagra-akamai
Copy link
Contributor Author

@jaalah-akamai / @abailly-akamai / @hkhalil-akamai can we have another approval & merge

Copy link
Contributor

@hkhalil-akamai hkhalil-akamai left a comment

Choose a reason for hiding this comment

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

Thanks for responding to feedback.

@nikhagra-akamai
Copy link
Contributor Author

@cpathipa @hkhalil-akamai thanks for the approvals

@nikhagra-akamai nikhagra-akamai added Approved Multiple approvals and ready to merge! and removed Ready for Review labels Sep 30, 2024
@jaalah-akamai jaalah-akamai merged commit 033099c into linode:develop Sep 30, 2024
20 checks passed
Copy link

cypress bot commented Sep 30, 2024

Cloud Manager E2E    Run #6596

Run Properties:  status check passed Passed #6596  •  git commit 033099ccf7: upcoming: [DI-20360] - Updated preferences logic to remove flickering issue (#10...
Project Cloud Manager E2E
Branch Review develop
Run status status check passed Passed #6596
Run duration 25m 12s
Commit git commit 033099ccf7: upcoming: [DI-20360] - Updated preferences logic to remove flickering issue (#10...
Committer Nikhil Agrawal
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 4
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 409
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! CloudPulse
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants