Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow DOM element via Portal #209

Closed
cometkim opened this issue Apr 7, 2020 · 10 comments
Closed

Allow DOM element via Portal #209

cometkim opened this issue Apr 7, 2020 · 10 comments

Comments

@cometkim
Copy link
Contributor

cometkim commented Apr 7, 2020

Description

Hi again! I'm currently doing research using react-pixi, and it works pretty well :)

However, I wanna build a UI layer separately using ReactDOM and communicating via custom Portal element.

Building UI in DOM and CSS is a good way to build responsive, constraint UI. But react-pixi seems doesn't allow dom element only text nodes inside of <Stage/>.

Is it possible to allow elements wrapped in Portal as an exception? Or provide prebuilt UI Portal?

@cometkim
Copy link
Contributor Author

cometkim commented Apr 8, 2020

I've confirmed that we can use it by simply adding the createTextInstance implementation.

The rootContainerInstance is passed to the dom node as is passed to ReactDOM.createPortal(), so I can use ReactDOM's implementation if the node is DOM element.

@inlet
Copy link
Collaborator

inlet commented Apr 8, 2020

Awesome, feel free to create a PR. Thanks!

@cometkim
Copy link
Contributor Author

cometkim commented Apr 9, 2020

I have tried yesterday, for all interfaces accessible via React and ReactDOM internals but I haven't found a way to delegate the remaining work to ReactDOM. (It was only possible to get rid of the error.)

It doesn't seem to be implemented yet.

facebook/react#13332

This issue is an important part of the custom renderer usability, so I need to keep following.

there are a couple of potentially possible ways to use DOM in react-pixi:

  • Embedding tiny reconciler implementation of DOM rendering.
  • Notify every change to external ReactDOM through "Bridge".

But closing this because I don't think these are react-pixi's.

@cometkim cometkim closed this as completed Apr 9, 2020
@inlet
Copy link
Collaborator

inlet commented Apr 9, 2020

Bummer, yes I think the "Bridge" option might be a good fit. Keep me posted once you've found a good solution.

Thanks!

@cometkim
Copy link
Contributor Author

cometkim commented Apr 10, 2020

@inlet Just implemented a simple bridge to outside root, and works well for elements 👍

https://github.com/devsisters/react-pixi#ui-portal

I'll post a codepen demo soon after modifying the deployment settings a bit.

@cometkim
Copy link
Contributor Author

cometkim commented Apr 10, 2020

Hmm... context or suspense still doesn't work via a bridge. I'm still looking for a way to pass it from React internals.

But I think this is enough to building a simple UI overlay.

@inlet
Copy link
Collaborator

inlet commented Apr 10, 2020

Context simple doesn’t work, this is a limitation of the React Context API. Not sure if the Suspense API is part of ReactDOM, but my first guess would be that is should work with custom renderers

@cometkim
Copy link
Contributor Author

cometkim commented Apr 15, 2020

https://github.com/devsisters/react-pixi/blob/master/src/experimental/portal/portal.tsx

@inlet I added shared context implementation for the Portal API.

Demo: https://codesandbox.io/s/react-pixi-portal-lsgh1?file=/src/Portal.js

import React from "react";
import ReactDOM from "react-dom";
import { Portal, createBridge } from "@devsisters/react-pixi";
import { CountContext } from "./countContext";

const $uiRoot = document.getElementById("ui-root");
const uiRoot = ReactDOM.createRoot($uiRoot);
const uiBridge = createBridge(uiRoot, {
  sharedContext: [CountContext],
});

const UIPortal = ({ children }) => {
  return <Portal bridge={uiBridge}>{children}</Portal>;
};

export default UIPortal;

So users can optionally specify the contexts to "capture" on the bridge, and these context values will automatically be forwarded when rendering.

@inlet
Copy link
Collaborator

inlet commented Apr 15, 2020

Nice work @cometkim !

@cometkim
Copy link
Contributor Author

cometkim commented Apr 15, 2020

There are some limitations in reading the context.

  • As long as it is done (semi-)automatically, there is no way to optimize propagation through observedBits.
  • Context values can only be read during component (portal) rendering (cannot be any other place like inside hooks, etc.)

I am wondering if there is a better interface than this. @inlet Do you have any opinion here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants