react-babylonjs icon indicating copy to clipboard operation
react-babylonjs copied to clipboard

How to understand the useCanvas() hook?

Open nene opened this issue 11 months ago • 2 comments

On first glance I though that this would be a useful hook to access the HTML <canvas> element on which the engine runs. Even the documentation says:

/**
 * Get the canvas DOM element from the context.
 */

But the types tell a different story:

export const useCanvas = (): Nullable<HTMLCanvasElement | WebGLRenderingContext>

The way I read it is that this hook might return a canvas or it might instead return WebGL context. I'm trying hard... but this makes no sense to me. Why would I use this hook? I can't use it to reliably access canvas. I also can't use it to reliably access WebGL context.

Well... given that I can access the canvas through WebGL context and also the other way around, I guess I could write some conditionals after this hook, like:

const maybeCanvas = useCanvas();
const canvas = maybeCanvas instanceof WebGLRenderingContext ? maybeCanvas.canvas : maybeCanvas;

But this feels silly.

Currently I have just implemented by own hook:

function useRenderingCanvas() {
  const engine = useEngine();
  return engine?.getRenderingCanvas();
}

So it's not really a problem for me any more. But it would still be good to understand the purpose of this useCanvas() hook.

nene avatar Jan 14 '25 15:01 nene

Although, AbstractEngine does return a canvas: https://doc.babylonjs.com/typedoc/classes/BABYLON.AbstractEngine#getrenderingcanvas

The constructor to engine can be also a context. https://github.com/BabylonJS/Babylon.js/blob/84580a00705d4513393988e3eb2cab0f2d9053b3/packages/dev/core/src/Engines/engine.ts#L363

I would say you are more correct though based on the name of the hook. I'm inclined to change the ReturnType<> to Nullable<HTMLCanvasElement>. People rendering to WebGLContext directly will be skilled enough to get from context on their own.

in typescript you can also write guard clauses like:

const isCanvas = (canvas: any) is HTMLCanvasElement => {
  return cause instanceof HTMLCanvasElement;
}

Probably the hook would check directly to HTMLCanvasElement, so there is no need for caller to assert non-null (!)

brianzinn avatar Jan 14 '25 21:01 brianzinn

I'll make that change in next couple of days. Thanks for the feedback.

brianzinn avatar Jan 14 '25 22:01 brianzinn