Skip to content

Commit 3938add

Browse files
committed
simplify
1 parent 58bd8c2 commit 3938add

File tree

1 file changed

+52
-96
lines changed

1 file changed

+52
-96
lines changed

module/source/hooks/use-unity-loader.ts

Lines changed: 52 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -22,120 +22,76 @@ const useUnityLoader = (unityConfig: UnityConfig): UnityLoaderStatus => {
2222
const [status, setStatus] = useState<UnityLoaderStatus>(
2323
UnityLoaderStatus.Loading
2424
);
25-
const { loaderUrl } = unityConfig;
26-
2725
// Effect hook will be invoked when the source changes.
2826
useEffect(() => {
2927
// It is possible for the application being rendered server side. In
3028
// this scenario, the window is not available. We can't create a Unity
3129
// Loader in this case.
32-
if (!isBrowserEnvironment) {
30+
if (isBrowserEnvironment === false) {
3331
return undefined;
3432
}
35-
3633
// If the script's source is null, we'll reset the status to idle.
37-
if (!loaderUrl) {
34+
if (unityConfig.loaderUrl === null) {
3835
setStatus(UnityLoaderStatus.Idle);
3936
return undefined;
4037
}
41-
42-
// Find existing script element by source.
43-
// It may have been added by another instance of this hook.
44-
let script = document.querySelector(
45-
`script[src="${loaderUrl}"]`
46-
) as HTMLScriptElement | null;
47-
48-
// Get existing data from the reference map.
49-
const existingData = scriptReferenceMap.get(loaderUrl);
50-
51-
if (script) {
52-
// If the script is already in the DOM, increment the ref count.
53-
if (existingData) {
54-
existingData.count += 1;
55-
scriptReferenceMap.set(loaderUrl, existingData);
56-
setStatus(existingData.status);
57-
} else {
58-
// Edge case: script is in the DOM, but not in the map.
59-
// (Unlikely if all usage is through this hook)
60-
scriptReferenceMap.set(loaderUrl, {
61-
count: 1,
62-
status: UnityLoaderStatus.Loaded,
63-
});
64-
setStatus(UnityLoaderStatus.Loaded);
65-
}
66-
} else {
67-
// Create a new script element.
68-
script = document.createElement("script");
38+
/**
39+
* Find existing script element by source. It may have been added by
40+
* another instance of this hook.
41+
*/
42+
let script: HTMLScriptElement | null = window.document.querySelector(
43+
`script[src="${unityConfig.loaderUrl}"]`
44+
);
45+
// If there wan't another instance of this script, we're going to create a
46+
// new one with the provided source.
47+
if (script === null) {
48+
script = window.document.createElement("script");
6949
script.type = "text/javascript";
70-
script.src = loaderUrl;
50+
script.src = unityConfig.loaderUrl;
7151
script.async = true;
7252
script.setAttribute("data-status", "loading");
73-
74-
// Define load handler.
75-
const handleLoad = () => {
76-
script?.setAttribute("data-status", "loaded");
77-
const refData = scriptReferenceMap.get(loaderUrl);
78-
if (refData) {
79-
refData.status = UnityLoaderStatus.Loaded;
80-
scriptReferenceMap.set(loaderUrl, refData);
81-
}
82-
setStatus(UnityLoaderStatus.Loaded);
83-
};
84-
85-
// Define error handler.
86-
const handleError = () => {
87-
script?.setAttribute("data-status", "error");
88-
const refData = scriptReferenceMap.get(loaderUrl);
89-
if (refData) {
90-
refData.status = UnityLoaderStatus.Error;
91-
scriptReferenceMap.set(loaderUrl, refData);
92-
}
93-
setStatus(UnityLoaderStatus.Error);
94-
};
95-
96-
// Attach listeners.
97-
script.addEventListener("load", handleLoad);
98-
script.addEventListener("error", handleError);
99-
100-
// Append the script to the document body.
101-
document.body.appendChild(script);
102-
103-
// Initialize the reference map.
104-
scriptReferenceMap.set(loaderUrl, {
105-
count: 1,
106-
status: UnityLoaderStatus.Loading,
107-
handleLoad,
108-
handleError,
109-
});
110-
111-
setStatus(UnityLoaderStatus.Loading);
53+
// Add script to window.document body.
54+
window.document.body.appendChild(script);
55+
// Store status in attribute on script. This can be read by other
56+
// instances of this hook.
57+
script.addEventListener("load", () =>
58+
script?.setAttribute("data-status", "loaded")
59+
);
60+
script.addEventListener("error", () =>
61+
script?.setAttribute("data-status", "error")
62+
);
63+
} else {
64+
// If there already was a script with the same source, grab its existing
65+
// script status from attribute and set to state.
66+
setStatus(
67+
script.getAttribute("data-status") === "loaded"
68+
? UnityLoaderStatus.Loaded
69+
: UnityLoaderStatus.Error
70+
);
11271
}
113-
72+
/**
73+
* Script event handler to update status in state. Even if the script
74+
* already exists we still need to add event handlers to update the state
75+
* for this hook instance.
76+
* @param event The event that was triggered.
77+
*/
78+
const setStateFromEvent = (event: Event) =>
79+
setStatus(
80+
event.type === "load"
81+
? UnityLoaderStatus.Loaded
82+
: UnityLoaderStatus.Error
83+
);
84+
script.addEventListener("load", setStateFromEvent);
85+
script.addEventListener("error", setStateFromEvent);
86+
// Remove event listeners on cleanup.
11487
return () => {
115-
const refData = scriptReferenceMap.get(loaderUrl);
116-
if (!refData) return;
117-
118-
// Decrement the ref count.
119-
refData.count -= 1;
120-
121-
// If there are no more consumers of the script, remove it from the DOM.
122-
if (refData.count <= 0) {
123-
scriptReferenceMap.delete(loaderUrl);
124-
125-
// Also remove listeners before removing the script.
126-
if (script && refData.handleLoad && refData.handleError) {
127-
script.removeEventListener("load", refData.handleLoad);
128-
script.removeEventListener("error", refData.handleError);
129-
}
130-
131-
script?.remove();
132-
} else {
133-
// If there's still at least one consumer of the script, update the map
134-
// but don't remove the script from the DOM.
135-
scriptReferenceMap.set(loaderUrl, refData);
88+
if (script !== null) {
89+
script.removeEventListener("load", setStateFromEvent);
90+
script.removeEventListener("error", setStateFromEvent);
91+
script.remove();
13692
}
13793
};
138-
}, [loaderUrl]);
94+
}, [unityConfig.loaderUrl]);
13995

14096
return status;
14197
};

0 commit comments

Comments
 (0)