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

View File

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

View File

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