1- import { createElement , HTMLAttributes , useEffect , useState , VFC } from 'react' ;
1+ import { HTMLAttributes , useEffect , useRef , useState , VFC } from 'react' ;
22
33import { useScript } from '../hooks/useScript' ;
44import { UnityContext } from '../lib/context' ;
@@ -20,7 +20,7 @@ export type UnityRendererProps = Omit<
2020 * @param {UnityRendererProps } props Configurtion context, Unity-specific
2121 * callback handlers and default React props for a `HTMLCanvasElement`.
2222 * Note that `ref` is not available due to internal use.
23- * @returns {( JSX.Element | null) } A `JSX.Element` containing the renderer,
23+ * @returns {JSX.Element | null } A `JSX.Element` containing the renderer,
2424 * or `null` if not initialized yet.
2525 */
2626export const UnityRenderer : VFC < UnityRendererProps > = ( {
@@ -33,10 +33,9 @@ export const UnityRenderer: VFC<UnityRendererProps> = ({
3333 const [ ctx , setCtx ] = useState < UnityContext | undefined > ( context ) ;
3434 const [ loaderState , setLoaderSource ] = useScript ( ctx ?. getConfig ( ) . loaderUrl ) ;
3535
36- // We cannot actually render the `HTMLCanvasElement`, so we need the `ref`
37- // for Unity and a `JSX.Element` for React rendering.
38- const [ canvas , setCanvas ] = useState < JSX . Element > ( ) ;
39- const [ renderer , setRenderer ] = useState < HTMLCanvasElement > ( ) ;
36+ // Reference to the actual <canvas> element, which has to be passed to
37+ // the native `createUnityInstance()` method.
38+ const canvas = useRef < HTMLCanvasElement > ( null ) ;
4039
4140 // This is the last state the game was in, either ready or not ready.
4241 // It is used to trigger `onUnityReadyStateChange` reliably.
@@ -104,18 +103,18 @@ export const UnityRenderer: VFC<UnityRendererProps> = ({
104103 * Unity instance.
105104 */
106105 async function mount ( ) : Promise < void > {
107- // if no context, renderer or loader is availiable , or the game is already loaded
108- if ( ! ctx || ! renderer || loaderState !== 'active' || lastReadyState ) {
106+ // if no context or loader is available , or the game is already loaded
107+ if ( ! ctx || ! canvas . current || loaderState !== 'active' || lastReadyState ) {
109108 throw new Error (
110- 'cannot mount unity instance without a context, loader or renderer '
109+ 'cannot mount unity instance without a context or loader '
111110 ) ;
112111 }
113112
114113 // get the current loader configuration from the UnityContext
115114 const c = ctx . getConfig ( ) ;
116115
117116 const instance = await window . createUnityInstance (
118- renderer ,
117+ canvas . current ,
119118 {
120119 dataUrl : c . dataUrl ,
121120 frameworkUrl : c . frameworkUrl ,
@@ -171,21 +170,9 @@ export const UnityRenderer: VFC<UnityRendererProps> = ({
171170 }
172171 } , [ loaderState ] ) ;
173172
174- // on mount
175- useEffect ( ( ) => {
176- // create the renderer and let the ref callback set its handle
177- setCanvas (
178- createElement ( 'canvas' , {
179- ref : ( r : HTMLCanvasElement ) => setRenderer ( r ) ,
180- ...canvasProps ,
181- } )
182- ) ;
183-
184- // on unmount
185- return ( ) => {
186- unmount ( ) ;
187- } ;
188- } , [ ] ) ;
173+ // on unmount
174+ useEffect ( ( ) => ( ) => unmount ( ) , [ ] ) ;
189175
190- return canvas || null ;
176+ // eslint-disable-next-line react/jsx-props-no-spreading
177+ return < canvas { ...canvasProps } ref = { canvas } /> ;
191178} ;
0 commit comments