evilfer / react-phaser

Other
101 stars 16 forks source link

How to inject existing react tree with `reactPhaser.render` ? #7

Open kevzettler opened 7 years ago

kevzettler commented 7 years ago

The fact that this library encourages overridingReact.createClass and React.render is really confusing.

Say I have an existing react app wired up with react-router and stuff. I'm trying to render a phaser game on a react-router route. like /game that route is bound to a simple component

import React from 'react';

const GameContainer = React.createClass({
  render: function(){
    return (
        <div className="game-page">
          <div className="phaser-container"></div>
        </div>
    );
  }
});

export default GameContainer;

I now want to hook this component up to react-phaser what do I do?

import React from 'react';
import ReactPhaser, { game } from 'react-phaser';

const MyGame = ReactPhaser.createClass({
  render: function(){
    return <game />;
  }
});

const GameContainer = React.createClass({
  componentDidMount: function(){
    ReactPhaser.render(<MyGame />, 'phaser-container');
  },

  render: function(){
    return (
        <div className="game-page">
          <div className="phaser-container"></div>
        </div>
    );
  }
});

export default GameContainer;
evilfer commented 7 years ago

React-phaser was thought for Phaser only games, not to combine Phaser with react/dom. I don't think this library can work with your code: react-phaser needs to modify React, in order to hook its own tags. In react-phaser "game", "body" etc are not typical react components created using React.createClass. They are simply text strings. React-phaser modifies react in order to hook these string tags to certain manipulations of Phaser objects. In the process, react-phaser removes react/dom, so "div" tags have no effect.

As a result of this implementation, you cannot import {game} from react-phaser: it'll be undefined.

I can see two solutions:

kevzettler commented 7 years ago

Interoperability with vanilla react is a common and expected pattern. You see this in libraries like:

https://github.com/Izzimach/react-three https://github.com/Flipboard/react-canvas https://github.com/Izzimach/react-pixi *Phaser is built on top of Pixi https://github.com/chrbala/react-audio

evilfer commented 7 years ago

Hi kevttler,

Please correct me if I'm wrong, but I had the impression that there was a trend in React development to separate React from react-dom. React-phaser has the goal of being compatible (obviously) with React, but not with react-dom, in a similar way as react-native (is it correct to assume that react-native is not interoperable with react-dom?)

So react-phaser is simply a react implementation without react-dom. As I mention, it's perfectly possible to implement react-phaser in a similar way as react-three: on top of react+react-dom. It may even have better performance! I chose not to do so thinking of html5, phaser only, mobile games, where the DOM would be mininal.

I'm sorry if the (poor) documentation gave you the wrong idea and you spent time with react-phaser. I tried to make it clear that react-phaser uses React's VDOM, but not the browser's DOM.

kevzettler commented 7 years ago

in a similar way as react-native (is it correct to assume that react-native is not interoperable with react-dom?)

I feel react-native is not an appropriate comparison. react-native is not interoperable with react-dom because it operates in an ecosystem ( mobile apps) that don't even have a DOM. I feel that being Phaser is an HTML5 - browser only game engine. It is fair to assume there will be a DOM around.

The 5 other examples I listed:

https://github.com/Izzimach/react-three https://github.com/Flipboard/react-canvas https://github.com/Izzimach/react-pixi *Phaser is built on top of Pixi https://github.com/chrbala/react-audio

Are aware that they operate in a DOM environment and will most likely have to integrate with an existing react-dom project.

This issue prevents using the DOM for in-game UI. it is a common pattern to render browser DOM UI alongside or over a game canvas. Browsers are highly optimized for HTML/CSS rendering and building Game UI alongside React components is a powerful workflow.

evilfer commented 7 years ago

Yeah that's a fair point :).

All I had read until now on Phaser was about no-dom apps. react-native could be a suitable comparison perhaps if you consider environments such as http://docs.cocoon.io/article/canvas-engine/.

But I definitely see the benefit of DOM based gui elements. They would make sense specially when using JSX code obviously. However, I think you wouldn't be able to really mix the components, only to create a Phaser canvas and an HTML overlay (which is the case of react-three anyway, for instance).

I don't think the code in this library can be easily converted to a react-dom based implementation, but I'm sure there must be already other alternatives built that way. Perhaps it was the way to go from the start...

kevzettler commented 7 years ago

I don't think the code in this library can be easily converted to a react-dom based implementation, but I'm sure there must be already other alternatives built that way. Perhaps it was the way to go from the start...

I appreciate the feedback @evilfer Thats what I was hoping to explore with this thread thanks for clarifying everything.

pradeeproark commented 7 years ago

I find this conversation interesting. Besides integration with DOM, how does this approach in react-phaser affect things like extensibility to add new phaser objects as tags. I also don’t understand why this approach might be less performant than having a full react tree. is it because the react engine wouldn’t know how to do reconciliation ?

If a different approach were to be tried, would using something like react-faux-dom be a better approach. Suggested here http://oli.me.uk/2015/09/09/d3-within-react-the-right-way/