Clean up dynamically inserted assets when template is unmounted #274

This commit is contained in:
garronej
2023-04-19 03:20:22 +02:00
parent 2bf3296c0f
commit cf1e595ba2
3 changed files with 45 additions and 22 deletions

View File

@ -15,7 +15,7 @@ export function usePrepareTemplate(params: {
htmlClassName: string | undefined; htmlClassName: string | undefined;
bodyClassName: string | undefined; bodyClassName: string | undefined;
}) { }) {
const { doFetchDefaultThemeResources, stylesCommon, styles, url, scripts, htmlClassName, bodyClassName } = params; const { doFetchDefaultThemeResources, stylesCommon = [], styles = [], url, scripts = [], htmlClassName, bodyClassName } = params;
const [isReady, setReady] = useReducer(() => true, !doFetchDefaultThemeResources); const [isReady, setReady] = useReducer(() => true, !doFetchDefaultThemeResources);
@ -26,36 +26,49 @@ export function usePrepareTemplate(params: {
let isUnmounted = false; let isUnmounted = false;
Promise.all( const removeArray: (() => void)[] = [];
(async () => {
const prLoadedArray: Promise<void>[] = [];
[ [
...(stylesCommon ?? []).map(relativePath => pathJoin(url.resourcesCommonPath, relativePath)), ...stylesCommon.map(relativePath => pathJoin(url.resourcesCommonPath, relativePath)),
...(styles ?? []).map(relativePath => pathJoin(url.resourcesPath, relativePath)) ...styles.map(relativePath => pathJoin(url.resourcesPath, relativePath))
] ]
.reverse() .reverse()
.map(href => .forEach(href => {
headInsert({ const { prLoaded, remove } = headInsert({
"type": "css", "type": "css",
href, "position": "prepend",
"position": "prepend" href
}) });
)
).then(() => { removeArray.push(remove);
prLoadedArray.push(prLoaded);
});
await Promise.all(prLoadedArray);
if (isUnmounted) { if (isUnmounted) {
return; return;
} }
setReady(); setReady();
}); })();
(scripts ?? []).forEach(relativePath => scripts.forEach(relativePath => {
headInsert({ const { remove } = headInsert({
"type": "javascript", "type": "javascript",
"src": pathJoin(url.resourcesPath, relativePath) "src": pathJoin(url.resourcesPath, relativePath)
}) });
);
removeArray.push(remove);
});
return () => { return () => {
isUnmounted = true; isUnmounted = true;
removeArray.forEach(remove => remove());
}; };
}, []); }, []);

View File

@ -22,17 +22,24 @@ export default function LoginOtp(props: PageProps<Extract<KcContext, { pageId: "
useEffect(() => { useEffect(() => {
let isCleanedUp = false; let isCleanedUp = false;
headInsert({ const { prLoaded, remove } = headInsert({
"type": "javascript", "type": "javascript",
"src": pathJoin(kcContext.url.resourcesCommonPath, "node_modules/jquery/dist/jquery.min.js") "src": pathJoin(kcContext.url.resourcesCommonPath, "node_modules/jquery/dist/jquery.min.js")
}).then(() => { });
if (isCleanedUp) return;
(async () => {
await prLoaded;
if (isCleanedUp) {
return;
}
evaluateInlineScript(); evaluateInlineScript();
}); })();
return () => { return () => {
isCleanedUp = true; isCleanedUp = true;
remove();
}; };
}, []); }, []);

View File

@ -12,7 +12,7 @@ export function headInsert(
type: "javascript"; type: "javascript";
src: string; src: string;
} }
) { ): { remove: () => void; prLoaded: Promise<void> } {
const htmlElement = document.createElement( const htmlElement = document.createElement(
(() => { (() => {
switch (params.type) { switch (params.type) {
@ -66,5 +66,8 @@ export function headInsert(
})() })()
](htmlElement); ](htmlElement);
return dLoaded.pr; return {
"prLoaded": dLoaded.pr,
"remove": () => htmlElement.remove()
};
} }