AppChrome: Fix race condition when updating chrome state on route changed (#52694)
This commit is contained in:
@@ -8,7 +8,7 @@ import { isShallowEqual } from 'app/core/utils/isShallowEqual';
|
||||
import { RouteDescriptor } from '../../navigation/types';
|
||||
|
||||
export interface AppChromeState {
|
||||
chromeless: boolean;
|
||||
chromeless?: boolean;
|
||||
sectionNav: NavModelItem;
|
||||
pageNav?: NavModelItem;
|
||||
actions?: React.ReactNode;
|
||||
@@ -20,6 +20,8 @@ const defaultSection: NavModelItem = { text: 'Grafana' };
|
||||
|
||||
export class AppChromeService {
|
||||
searchBarStorageKey = 'SearchBar_Hidden';
|
||||
private currentRoute?: RouteDescriptor;
|
||||
private routeChangeHandled?: boolean;
|
||||
|
||||
readonly state = new BehaviorSubject<AppChromeState>({
|
||||
chromeless: true, // start out hidden to not flash it on pages without chrome
|
||||
@@ -27,22 +29,30 @@ export class AppChromeService {
|
||||
searchBarHidden: store.getBool(this.searchBarStorageKey, false),
|
||||
});
|
||||
|
||||
routeMounted(route: RouteDescriptor) {
|
||||
this.update({
|
||||
chromeless: route.chromeless === true,
|
||||
sectionNav: defaultSection,
|
||||
pageNav: undefined,
|
||||
actions: undefined,
|
||||
});
|
||||
registerRouteRender(route: RouteDescriptor) {
|
||||
if (this.currentRoute !== route) {
|
||||
this.currentRoute = route;
|
||||
this.routeChangeHandled = false;
|
||||
}
|
||||
}
|
||||
|
||||
update(state: Partial<AppChromeState>) {
|
||||
update(update: Partial<AppChromeState>) {
|
||||
const current = this.state.getValue();
|
||||
const newState: AppChromeState = {
|
||||
...current,
|
||||
...state,
|
||||
};
|
||||
|
||||
// when route change update props from route and clear fields
|
||||
if (!this.routeChangeHandled) {
|
||||
newState.actions = undefined;
|
||||
newState.pageNav = undefined;
|
||||
newState.sectionNav = defaultSection;
|
||||
newState.chromeless = this.currentRoute?.chromeless;
|
||||
this.routeChangeHandled = true;
|
||||
}
|
||||
|
||||
Object.assign(newState, update);
|
||||
|
||||
if (!isShallowEqual(current, newState)) {
|
||||
this.state.next(newState);
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ export interface Props extends Omit<GrafanaRouteComponentProps, 'queryParams'> {
|
||||
export function GrafanaRoute(props: Props) {
|
||||
const { chrome } = useGrafana();
|
||||
|
||||
useEffect(() => {
|
||||
chrome.routeMounted(props.route);
|
||||
chrome.registerRouteRender(props.route);
|
||||
|
||||
useEffect(() => {
|
||||
updateBodyClassNames(props.route);
|
||||
cleanupDOM();
|
||||
reportPageview();
|
||||
@@ -26,7 +26,9 @@ export function GrafanaRoute(props: Props) {
|
||||
navigationLogger('GrafanaRoute', false, 'Unmounted', props.route);
|
||||
updateBodyClassNames(props.route, true);
|
||||
};
|
||||
}, [chrome, props.route, props.match]);
|
||||
// props.match instance change even though only query params changed so to make this effect only trigger on route mount we have to disable exhaustive-deps
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// unbinds all and re-bind global keybindins
|
||||
|
||||
Reference in New Issue
Block a user