@@ -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