fix(techdocs): avoid rerender current page when navigating to another (#26944)
Signed-off-by: Thomas Cardonne <thomas.cardonne@adevinta.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs-react': patch
|
||||
'@backstage/plugin-techdocs': patch
|
||||
---
|
||||
|
||||
Fix an issue that caused the current documentation page to be re-rendered when navigating to
|
||||
another one.
|
||||
@@ -64,24 +64,6 @@ describe('TechDocsShadowDom', () => {
|
||||
expect(onAppend).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('Should show progress bar while styles are being loaded', async () => {
|
||||
const dom = createDom(
|
||||
'<head><link rel="stylesheet" src="styles.css"/></head><body><h1>Title</h1></body>',
|
||||
);
|
||||
const onAppend = jest.fn();
|
||||
dom.querySelector('link[rel="stylesheet"]')!.addEventListener = () => {};
|
||||
|
||||
render(
|
||||
<TechDocsShadowDom element={dom} onAppend={onAppend}>
|
||||
Children
|
||||
</TechDocsShadowDom>,
|
||||
);
|
||||
|
||||
await await waitFor(() => {
|
||||
expect(screen.getByRole('progressbar')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('Should dispatch an event after all styles are loaded', async () => {
|
||||
const dom = createDom(
|
||||
'<head><link rel="stylesheet" src="styles.css"/></head><body><h1>Title</h1></body>',
|
||||
@@ -98,16 +80,8 @@ describe('TechDocsShadowDom', () => {
|
||||
|
||||
render(<TechDocsShadowDom element={dom}>Children</TechDocsShadowDom>);
|
||||
|
||||
await await waitFor(() => {
|
||||
expect(screen.getByRole('progressbar')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
listener({} as Event);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(handleStylesLoad).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,8 +25,6 @@ import { create } from 'jss';
|
||||
import StylesProvider from '@material-ui/styles/StylesProvider';
|
||||
import jssPreset from '@material-ui/styles/jssPreset';
|
||||
|
||||
import { Progress } from '@backstage/core-components';
|
||||
|
||||
/**
|
||||
* Name for the event dispatched when ShadowRoot styles are loaded.
|
||||
* @public
|
||||
@@ -216,7 +214,6 @@ export const TechDocsShadowDom = (props: TechDocsShadowDomProps) => {
|
||||
);
|
||||
|
||||
useShadowDomStylesEvents(element);
|
||||
const loading = useShadowDomStylesLoading(element);
|
||||
|
||||
const ref = useCallback(
|
||||
(shadowHost: HTMLDivElement) => {
|
||||
@@ -246,7 +243,6 @@ export const TechDocsShadowDom = (props: TechDocsShadowDomProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{loading && <Progress />}
|
||||
{/* The sheetsManager={new Map()} is needed in order to deduplicate the injection of CSS in the page. */}
|
||||
<StylesProvider jss={jss} sheetsManager={new Map()}>
|
||||
<div ref={ref} data-testid="techdocs-native-shadowroot" />
|
||||
|
||||
+38
-1
@@ -34,9 +34,11 @@ jest.mock('../useReaderState', () => ({
|
||||
...jest.requireActual('../useReaderState'),
|
||||
useReaderState: (...args: any[]) => useReaderState(...args),
|
||||
}));
|
||||
const useShadowDomStylesLoading = jest.fn().mockReturnValue(false);
|
||||
jest.mock('@backstage/plugin-techdocs-react', () => ({
|
||||
...jest.requireActual('@backstage/plugin-techdocs-react'),
|
||||
useShadowDomStylesLoading: jest.fn().mockReturnValue(false),
|
||||
useShadowDomStylesLoading: (...args: any[]) =>
|
||||
useShadowDomStylesLoading(...args),
|
||||
useShadowRootElements: jest.fn(),
|
||||
}));
|
||||
|
||||
@@ -220,4 +222,39 @@ describe('<TechDocsReaderPageContent />', () => {
|
||||
|
||||
window.location.hash = '';
|
||||
});
|
||||
|
||||
it('should render progress bar when content is loading', async () => {
|
||||
getEntityMetadata.mockResolvedValue(mockEntityMetadata);
|
||||
getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata);
|
||||
useTechDocsReaderDom.mockReturnValue(document.createElement('html'));
|
||||
useReaderState.mockReturnValue({ state: 'CHECKING' });
|
||||
|
||||
const rendered = await renderInTestApp(
|
||||
<Wrapper>
|
||||
<TechDocsReaderPageContent withSearch={false} />
|
||||
</Wrapper>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(rendered.queryByRole('progressbar')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should render progress bar when styles are loading', async () => {
|
||||
getEntityMetadata.mockResolvedValue(mockEntityMetadata);
|
||||
getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata);
|
||||
useTechDocsReaderDom.mockReturnValue(document.createElement('html'));
|
||||
useReaderState.mockReturnValue({ state: 'cached' });
|
||||
useShadowDomStylesLoading.mockReturnValue(true);
|
||||
|
||||
const rendered = await renderInTestApp(
|
||||
<Wrapper>
|
||||
<TechDocsReaderPageContent withSearch={false} />
|
||||
</Wrapper>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(rendered.queryByRole('progressbar')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+8
-2
@@ -26,13 +26,16 @@ import {
|
||||
useTechDocsReaderPage,
|
||||
} from '@backstage/plugin-techdocs-react';
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import { Content, ErrorPage } from '@backstage/core-components';
|
||||
import { Content, ErrorPage, Progress } from '@backstage/core-components';
|
||||
|
||||
import { TechDocsSearch } from '../../../search';
|
||||
import { TechDocsStateIndicator } from '../TechDocsStateIndicator';
|
||||
|
||||
import { useTechDocsReaderDom } from './dom';
|
||||
import { withTechDocsReaderProvider } from '../TechDocsReaderProvider';
|
||||
import {
|
||||
useTechDocsReader,
|
||||
withTechDocsReaderProvider,
|
||||
} from '../TechDocsReaderProvider';
|
||||
import { TechDocsReaderPageContentAddons } from './TechDocsReaderPageContentAddons';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
@@ -81,6 +84,7 @@ export const TechDocsReaderPageContent = withTechDocsReaderProvider(
|
||||
entityRef,
|
||||
setShadowRoot,
|
||||
} = useTechDocsReaderPage();
|
||||
const { state } = useTechDocsReader();
|
||||
const dom = useTechDocsReaderDom(entityRef);
|
||||
const path = window.location.pathname;
|
||||
const hash = window.location.hash;
|
||||
@@ -143,6 +147,8 @@ export const TechDocsReaderPageContent = withTechDocsReaderProvider(
|
||||
)}
|
||||
<Grid xs={12} item>
|
||||
{/* Centers the styles loaded event to avoid having multiple locations setting the opacity style in Shadow Dom causing the screen to flash multiple times */}
|
||||
{(state === 'CHECKING' || isStyleLoading) && <Progress />}
|
||||
|
||||
<TechDocsShadowDom element={dom} onAppend={handleAppend}>
|
||||
<TechDocsReaderPageContentAddons />
|
||||
</TechDocsShadowDom>
|
||||
|
||||
@@ -276,6 +276,12 @@ export const useTechDocsReaderDom = (
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip this update if the location's path has changed but the state
|
||||
// contains a page for another page that isn't loaded yet.
|
||||
if (!window.location.pathname.endsWith(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scroll to top after render
|
||||
window.scroll({ top: 0 });
|
||||
|
||||
@@ -283,6 +289,7 @@ export const useTechDocsReaderDom = (
|
||||
const postTransformedDomElement = await postRender(
|
||||
preTransformedDomElement,
|
||||
);
|
||||
|
||||
setDom(postTransformedDomElement as HTMLElement);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user