From 468ca0f9b3388878a30f05996d81af0351f943ce Mon Sep 17 00:00:00 2001 From: Bilawal Hameed Date: Fri, 3 Jul 2020 16:03:38 +0200 Subject: [PATCH] fix(techdocs): fixed race condition between page loads --- .../techdocs/src/reader/components/Reader.tsx | 21 ++++++++----- .../techdocs/src/reader/hooks/shadowDom.ts | 30 ++++++++++++++----- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 995d9dc99f..bd7ac17a6a 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -35,15 +35,22 @@ import { TechDocsPageWrapper } from './TechDocsPageWrapper'; const useFetch = (url: string): AsyncState => { const state = useAsync(async () => { - const response = await fetch(url); - if (response.status === 404) { - return new Error('Page not found'); + const request = await fetch(url); + if (request.status === 404) { + return [request.url, new Error('Page not found')]; } - const raw = await response.text(); - return raw; + const response = await request.text(); + return [request.url, response]; }, [url]); - return state; + const [fetchedUrl, fetchedValue] = state.value ?? []; + + if (url !== fetchedUrl) { + // Fixes a race condition between two pages + return { loading: true }; + } + + return Object.assign(state, fetchedValue ? { value: fetchedValue } : {}); }; const useEnforcedTrailingSlash = (): void => { @@ -60,7 +67,7 @@ const useEnforcedTrailingSlash = (): void => { export const Reader = () => { const location = useLocation(); const { componentId, '*': path } = useParams(); - const shadowDomRef = useShadowDom(); + const [ref, shadowRoot] = useShadowDom(componentId, path); const navigate = useNavigate(); const normalizedUrl = new URLFormatter( `${docStorageURL}${location.pathname.replace('/docs', '')}`, diff --git a/plugins/techdocs/src/reader/hooks/shadowDom.ts b/plugins/techdocs/src/reader/hooks/shadowDom.ts index 5edb8f4e4d..90b287e343 100644 --- a/plugins/techdocs/src/reader/hooks/shadowDom.ts +++ b/plugins/techdocs/src/reader/hooks/shadowDom.ts @@ -17,14 +17,30 @@ import { useEffect, useRef } from 'react'; import type { RefObject } from 'react'; -type IShadowDOMRefObject = RefObject; -export const useShadowDom: () => IShadowDOMRefObject = () => { - const ref: IShadowDOMRefObject = useRef(null); +type IUseShadowDOM = ( + componentId: string, + path: string, +) => [RefObject, ShadowRoot?]; + +export const useShadowDom: IUseShadowDOM = (componentId, path) => { + const ref = useRef(null); useEffect(() => { - const divElement = ref.current; - divElement?.attachShadow({ mode: 'open' }); - }, [ref]); + const innerDivElement = document.createElement('div'); + innerDivElement.attachShadow({ mode: 'open' }); - return ref; + const outerDivElement = ref.current; + outerDivElement?.appendChild(innerDivElement); + + return function cancel() { + outerDivElement?.removeChild(innerDivElement); + }; + }, [componentId, path]); + + const shadowRoot = + ref.current?.children && ref.current?.children[0].shadowRoot + ? ref.current?.children[0].shadowRoot + : undefined; + + return [ref, shadowRoot]; };