Claire Cashmore
Claire Cashmore

Reputation: 3

Why are multiple canvases being made in my Phaser/React app?

I am trying to develop a phaser3 application with React. I am just setting up the first canvas for the Phaser.Game. Here is my App.js from the create-react-app.

import "./App.css";
import Phaser, { Game } from "phaser";
import PhaserMatterCollisionPlugin from "phaser-matter-collision-plugin";
import { useCallback, useEffect, useState } from "react";

function App() {
  const [game, setGame] = useState(null);
  // Creating game inside a useEffect in order to ensure 1 instance is created
  console.log("before use effect");
  useEffect(() => {
    console.log("Going into useEffect");
    console.log(game);
    if (game) {
      console.log("game detected. stop creation");
      return;
    }
    const phaserGame = new Phaser.Game({
      width: 512,
      height: 412,
      backgroundColor: "#333333",
      type: Phaser.AUTO,
      parent: "survival-game",
      scene: [],
      scale: {
        zoom: 2,
      },
      physics: {
        default: "matter",
        matter: {
          debug: true,
          gravity: { y: 0 },
        },
      },
      plugins: {
        scene: [
          {
            plugin: PhaserMatterCollisionPlugin,
            key: "matterCollision",
            mapping: "matterCollision",
          },
        ],
      },
    });

    setGame(true);
    return;
  }, [game]);
}

export default App;

I used useEffect() with useState in order to prevent multiple game instances, but for some reason I am still getting a duplicate canvas and can see that it is running through the useEffect multiple times. console.log of the react app

Upvotes: 0

Views: 1072

Answers (1)

AKX
AKX

Reputation: 169022

You should use a ref instead of state for the game object. Here's a small custom hook that sets up a Phaser.Game based on a given configuration:

function usePhaserGame(config) {
  const phaserGameRef = React.useRef(null);
  React.useEffect(() => {
    if (phaserGameRef.current) {
      return;
    }
    phaserGameRef.current = new Game(config);
    return () => {
      phaserGameRef.current.destroy(true);
      phaserGameRef.current = null;
    };
  }, [] /* only run once; config ref elided on purpose */);
  return phaserGameRef.current;
}

const config = {
  width: 512,
  height: 412,
  backgroundColor: '#333333',
  type: Phaser.AUTO,
  parent: 'survival-game',
  scene: [],
  scale: {
    zoom: 2,
  },
  physics: {
    default: 'matter',
    matter: {
      debug: true,
      gravity: {y: 0},
    },
  },
  plugins: {
    scene: [
      {
        plugin: PhaserMatterCollisionPlugin,
        key: 'matterCollision',
        mapping: 'matterCollision',
      },
    ],
  },
};

function App() {
  const game = usePhaserGame(config);
}

Upvotes: 4

Related Questions