mirror of
https://github.com/grafana/grafana.git
synced 2025-02-14 01:23:32 -06:00
AppChrome: Reduce re-renders for identical pageNavs (#62483)
* AppChrome: Reduce re-renders for identical pageNavs * Update * removed log
This commit is contained in:
parent
b1e58eb47e
commit
39537043ec
@ -7,4 +7,33 @@ describe('AppChromeService', () => {
|
||||
chromeService.onToggleKioskMode();
|
||||
expect(chromeService.state.getValue().chromeless).toBe(true);
|
||||
});
|
||||
|
||||
it('Ignore state updates when sectionNav and pageNav have new instance but same text, url or active child', () => {
|
||||
const chromeService = new AppChromeService();
|
||||
let stateChanges = 0;
|
||||
|
||||
chromeService.state.subscribe(() => stateChanges++);
|
||||
chromeService.update({ sectionNav: { text: 'hello' }, pageNav: { text: 'test', url: 'A' } });
|
||||
chromeService.update({ sectionNav: { text: 'hello' }, pageNav: { text: 'test', url: 'A' } });
|
||||
|
||||
expect(stateChanges).toBe(2);
|
||||
|
||||
// if url change we should update
|
||||
chromeService.update({ sectionNav: { text: 'hello' }, pageNav: { text: 'test', url: 'new/url' } });
|
||||
expect(stateChanges).toBe(3);
|
||||
|
||||
// if active child changed should update state
|
||||
chromeService.update({
|
||||
sectionNav: { text: 'hello' },
|
||||
pageNav: { text: 'test', url: 'A', children: [{ text: 'child', active: true }] },
|
||||
});
|
||||
expect(stateChanges).toBe(4);
|
||||
|
||||
// If active child is the same we should not update state
|
||||
chromeService.update({
|
||||
sectionNav: { text: 'hello' },
|
||||
pageNav: { text: 'test', url: 'A', children: [{ text: 'child', active: true }] },
|
||||
});
|
||||
expect(stateChanges).toBe(4);
|
||||
});
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ export interface AppChromeState {
|
||||
export class AppChromeService {
|
||||
searchBarStorageKey = 'SearchBar_Hidden';
|
||||
private currentRoute?: RouteDescriptor;
|
||||
private routeChangeHandled?: boolean;
|
||||
private routeChangeHandled = true;
|
||||
|
||||
readonly state = new BehaviorSubject<AppChromeState>({
|
||||
chromeless: true, // start out hidden to not flash it on pages without chrome
|
||||
@ -60,11 +60,29 @@ export class AppChromeService {
|
||||
// KioskMode overrides chromeless state
|
||||
newState.chromeless = newState.kioskMode === KioskMode.Full || this.currentRoute?.chromeless;
|
||||
|
||||
if (!isShallowEqual(current, newState)) {
|
||||
if (!this.ignoreStateUpdate(newState, current)) {
|
||||
this.state.next(newState);
|
||||
}
|
||||
}
|
||||
|
||||
ignoreStateUpdate(newState: AppChromeState, current: AppChromeState) {
|
||||
if (isShallowEqual(newState, current)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Some updates can have new instance of sectionNav or pageNav but with same values
|
||||
if (newState.sectionNav !== current.sectionNav || newState.pageNav !== current.pageNav) {
|
||||
if (
|
||||
navItemsAreTheSame(newState.sectionNav, current.sectionNav) &&
|
||||
navItemsAreTheSame(newState.pageNav, current.pageNav)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
useState() {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
return useObservable(this.state, this.state.getValue());
|
||||
@ -134,3 +152,17 @@ export class AppChromeService {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if text, url and active child url are the same
|
||||
**/
|
||||
function navItemsAreTheSame(a: NavModelItem | undefined, b: NavModelItem | undefined) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const aActiveChild = a?.children?.find((child) => child.active);
|
||||
const bActiveChild = b?.children?.find((child) => child.active);
|
||||
|
||||
return a?.text === b?.text && a?.url === b?.url && aActiveChild?.url === bActiveChild?.url;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user