How to toggle inline/portal in React

315 Views Asked by At

I have an app under <div id="app"> and a portal root element <div id="portal"> (https://reactjs.org/docs/portals.html).

ReactDOM.render(<App />, document.getElementById('app'));

I would like to toggle between inline and portal while video is playing.

I hope to avoid video from pausing, or at least user will not detect the pause.

Inline:

<body>
  <div id="app">
    <div>
      <button>Toggle inline/portal</button>
      <div class="inline">
        <video></video>
      </div>
    </div>
  </div>
  <div id="portal">
  </div>
</body>

Portal (css for frame full screen):

<body>
  <div id="app">
    <div>
      <button>Toggle inline/portal</button>
      <div class="inline">
      </div>
    </div>
  </div>
  <div id="portal">
    <video></video>
  </div>
</body>

Is this possible? How can I achieve it in React?

2

There are 2 best solutions below

0
On

You can just change the CSS conditionally instead of having two containers:

import { useState } from "react";

const App = () => {
  const [cssStyle, setCssStyle] = useState("inline");

  const toggleVideoMode = () => {
    const mode = cssStyle === "inline" ? "portal" : "inline";
    setCssStyle(mode);
  };

  return (
    <div>
      <button onClick={toggleVideoMode}>Toggle inline/portal</button>
      <div className={cssStyle}>
        <video><video>
      </div>
    </div>
  );
};

export default App;
0
On

This can be done easily by using state in React,

import { useState } from "react";
import "./styles.css";

function VideoComponent(props) {
  console.log(props)
  return <p>Hi I am a video, inline mode: {JSON.stringify(props.mode)}</p>;
}

export default function App() {
  const [inlineMode, setInlineMode] = useState(true);

  return (
    <div className="App">
        <div id="app">
        <div>
          <button onClick={()=>setInlineMode(!inlineMode)}>Toggle inline/portal</button>
          <div className="inline">
            {inlineMode && <VideoComponent mode={inlineMode}/>}
          </div>
        </div>
      </div>
      <div id="portal">
      {!inlineMode && <VideoComponent mode={inlineMode}/>}
      </div>
    </div>
  );
}

CodeSandbox sample