The Right Way to Set Up Phaser in ReactJS
Learn how to seamlessly integrate Phaser with ReactJS in this step-by-step guide. Whether you're building interactive games or adding game elements to your web app, this tutorial will ensure smooth performance and clean, maintainable code.

Phaser is a powerful game framework used to create browser-based games. ReactJS, on the other hand, is a popular library for building user interfaces. Combining these two can open up exciting possibilities for web developers, but setting up Phaser within a ReactJS application requires a bit of know-how. This guide will walk you through the correct way to integrate Phaser with React, ensuring smooth performance and maintainable code.
Pre-requisites
Before we dive in, make sure you have the following:
- Basic Knowledge of React: Understanding React components, hooks, and state management.
- Familiarity with Phaser: Know how to set up and run a basic Phaser game.
- Node.js Installed: Make sure Node.js is installed on your system.
If you prefer watching videos over reading, check out this YouTube video where I explain the setup process and discuss common issues you might face while integrating Phaser with React.
Setting up the React Application
First, you need to set up a ReactJS project. If you haven’t already created one, you can do so with Create React App, which is the quickest way to get started:
npx create-react-app phaser-app
Next, let's install Phaser:
npm install phaser
With these steps, we've set up our React environment and installed Phaser as a dependency.
Setting up Phaser
To create a Phaser game, we need to define a game configuration and a scene. We'll start by creating a React component that will instantiate the Phaser game using the provided configuration. This approach allows for modularity, enabling us to render multiple Phaser games if needed.
Here's the code for the component:
import React, { useEffect } from 'react';
import Phaser from 'phaser';
const GameRenderComp = ({ config }) => {
useEffect(() => {
const main = new Phaser.Game(config);
return () => {
main.destroy(true);
};
}, [config]);
return (
<div
style={{ width: "100vw", height: "100vh" }}
id="phaser-container"
/>
);
};
export default GameRenderComp;
This component takes a Phaser game configuration and creates a Phaser game instance when it's mounted. It also ensures that the game instance is destroyed when the component is unmounted.
Now, let's set up a Phaser game configuration so we can use the GameRenderComp
component to render a Phaser game:
const config = {
type: Phaser.AUTO,
parent: "phaser-container",
backgroundColor: "#2d2d2d", // Example dark gray shade
scale: {
mode: Phaser.Scale.EXPAND,
width: window.innerWidth * window.devicePixelRatio,
height: window.innerHeight * window.devicePixelRatio,
},
physics: {
default: "arcade",
arcade: {
gravity: { y: 100 },
debug: true,
},
},
resolution: 1,
scene: [TestScene],
};
Note the parent: "phaser-container"
property in the configuration. This must match the ID of the div
element in the GameRenderComp
component.
To render the Phaser game, you can use the GameRenderComp
in your routing setup:
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import GameRenderComp from './components/GameRenderComp';
const App = () => (
<Router>
<Routes>
<Route path="/game" element={<GameRenderComp config={config} />} />
</Routes>
</Router>
);
export default App;
Creating the Game Scene
Now, let's define a simple scene to test our setup. Create a TestScene
class, which will be the starting scene of our Phaser game:
import Phaser from 'phaser';
class TestScene extends Phaser.Scene {
preload() {
this.load.setBaseURL('https://labs.phaser.io');
this.load.image('sky', 'assets/skies/space3.png');
this.load.image('logo', 'assets/sprites/phaser3-logo.png');
this.load.image('red', 'assets/particles/red.png');
}
create() {
this.add.image(400, 300, 'sky');
const particles = this.add.particles(0, 0, 'red', {
speed: 100,
scale: { start: 1, end: 0 },
blendMode: 'ADD',
});
const logo = this.physics.add.image(400, 100, 'logo');
logo.setVelocity(100, 200);
logo.setBounce(1, 1);
logo.setCollideWorldBounds(true);
particles.startFollow(logo);
}
}
export default TestScene;
This is a basic scene, as outlined in Phaser's documentation. It includes a background, a logo, and some particle effects.
Directory Structure
To keep your project organized and scalable, you can structure your directory like this:
phaser-app/
├── src/
│ ├── assets/
│ ├── components/
| ├── GameRenderer.jsx
│ ├── pages/
| ├── game/
| ├── scenes/
| | └── TestScene.js
| └── config.js
│ ├── App.jsx
│ ├── index.jsx
├── .eslintrc.js
├── .prettierrc
├── package.json
└── package-lock.json
This structure is intuitive and supports scalability as your project grows.
That's it for this blog, if you face any problems feel free to drop a comment. I would love to resolve your query.
Frequently Asked Questions (FAQs)
Why is the phaser game rendered twice ?
This might be because you have StrictMode enabled in the React App. You can fix this by removing the StrictMode from the `index.js`
Why is the phaser game canvas outside of root?
This is because you have not specified the parent in the configuration of the game. The parent should be the ID of the div where you want to render the game, in this case, the div inside the GameRenderComponent.