tl;dr
I'd like to enforce the following invariant: when using useImperativeHandle, don't fill the ref until some other ref is filled.
Long version
I have weird components
I have a component that uses a custom function for creating a <canvas>. This function knows nothing about React and comes from an external library. It returns a methods object that can be used to interact with the canvas.
function createGame(...): GameMethods {...}
I also have a component (NextReactP5Wrapper) that calls this createGame function in a special way and manages the created <canvas>
function Game(props) {
return (
<NextReactP5Wrapper
sketch={(p5) => {
const methods = createGame(props.env, p5)
return
}}
/>
)
}
// Note: React doesn't guarantee that `memo` will not rerender.
// But so far it works, and I haven't found any other way.
const MemoizedGame = React.memo(Game, () => true)
What I want to do
I'd like to make the returned methods to be available wherever I'm using Game. So I'm using forwardRef and useImperativeHandle:
const Game = React.forwardRef<GameMethods, { env: GameAttributes }>(
function Game(props, ref) {
const methodsRef = React.useRef<GameMethods | null>(null)
React.useImperativeHandle(ref, () => ({
// thanks to 'current?' we get a potential null here
getFoo: () => methodsRef.current?.getFoo(),
}))
return (
<NextReactP5Wrapper
sketch={(p5) => {
const methods = createGame(props.env, p5)
gameMethods.current = methods
}}
/>
)
})
const MemoizedGame = React.memo(Game, () => true)
...elsewhere in my <Page> component
const gameRef = React.useRef<GameMethods>(null)
return <Game ref={gameRef}/>
My problem
Now I have a problem: gameRef.current can be null and the result of gameRef.current.getFoo() can also be null!
What I want
I'd like to make sure the imperative handle ref isn't filled until the result of createGame() is available. Then I can have an easier life, knowing that if gameRef.current !== null, I can call of its methods.
Is it possible?
Or should I just write gameMethods.current! everywhere I was writing gameMethods.current? and hope that everything will be fine?