React中创建Phaser 3 GameObject实例时出现重复Canvas组件问题
解决React组件中Phaser Canvas重复的问题
问题原因
你碰到的重复Canvas是因为React严格模式(React.StrictMode)在开发环境下会重复调用componentDidMount,导致你创建了两个Phaser.Game实例,自然生成了两个Canvas。生产环境下StrictMode不会有这个重复执行的行为,但开发阶段会触发这个校验逻辑。
解决方案
方案1:临时移除StrictMode(快速解决)
直接去掉根渲染代码里的<React.StrictMode>包裹,开发环境就不会重复执行生命周期方法了:
root.render( <Game /> );
注:StrictMode能帮你提前发现潜在问题,生产环境默认不会启用这个模式,所以这个方法适合快速验证问题根源。
方案2:组件内控制实例只创建一次(规范解法)
在类组件中添加实例变量记录Phaser实例状态,避免重复创建:
import Phaser from "phaser"; import React from "react"; export default class Game extends React.Component { private gameInstance: Phaser.Game | null = null; componentDidMount() { // 仅当实例不存在时才创建 if (!this.gameInstance) { const gameConfig: Phaser.Types.Core.GameConfig = { type: Phaser.AUTO, parent: 'game-container', backgroundColor: '#EBEBEB', width: 600, height: 800 } this.gameInstance = new Phaser.Game(gameConfig); } } componentWillUnmount() { // 组件卸载时销毁实例,避免内存泄漏 if (this.gameInstance) { this.gameInstance.destroy(true); this.gameInstance = null; } } shouldComponentUpdate() { return false; } render() { return <div id='game-container' /> } }
方案3:转函数组件用useEffect(推荐写法)
换成函数组件,结合useRef标记初始化状态,同时用ref获取容器元素(比id更可靠):
import Phaser from "phaser"; import React, { useEffect, useRef } from "react"; export default function Game() { const gameContainerRef = useRef<HTMLDivElement>(null); const gameInstanceRef = useRef<Phaser.Game | null>(null); useEffect(() => { if (!gameInstanceRef.current && gameContainerRef.current) { const gameConfig: Phaser.Types.Core.GameConfig = { type: Phaser.AUTO, parent: gameContainerRef.current, backgroundColor: '#EBEBEB', width: 600, height: 800 } gameInstanceRef.current = new Phaser.Game(gameConfig); } // 卸载时清理实例 return () => { if (gameInstanceRef.current) { gameInstanceRef.current.destroy(true); gameInstanceRef.current = null; } } }, []); return <div ref={gameContainerRef} /> }
内容的提问来源于stack exchange,提问作者Danii
相关产品推荐
相关产品推荐

