DEV Community

Deepak Mondal
Deepak Mondal

Posted on

Mounting a React component in a picture in picture window

Google has introduced the documentPictureInPicture API in chrome 116.

In this article we explore how to mount a simple react component in the picture in picture window without the need to first mount it on our main application.

Step 1 — Set up component structure
We make two components. MainComponent.js and Counter.js. In MainComponent.js we set up a simple button that will open up the Counter.js component in the PIP window.

MainComponent.js

import React from "react";

const MainComponent = () => {
 async function openPictureInPicture() {
  // 
 }

 return (
  <div>
   <div onClick={openPictureInPicture}>Open counter</div>
  </div>
 );
};

export default MainComponent;
Enter fullscreen mode Exit fullscreen mode

Counter.js

import React, { useState, useEffect } from "react";
const Counter = () => {
 const [count, setCount] = useState(0);

 useEffect(() => {
  setCount(1);
 }, []);

 const addNumber = () => {
  setCount((prevCount) => prevCount + 1);
 };
 const subtractNumber = () => {
  setCount((prevCount) => prevCount - 1);
 };

 try {
  return (
   <div>
    <div onClick={subtractNumber}>-</div>
    <button>{count}</button>
    <div onClick={addNumber}>+</div>
   </div>
  );
 } catch (error) {
  console.error("ERROR_CODE: _RENDER\n", error);
  return <></>;
 }
};

export default Counter;
Enter fullscreen mode Exit fullscreen mode

Step 2 — Add the picture in picture functionality
In the openPictureInPicture() function we request for a picture in picture window.

const pipWindow = await window.documentPictureInPicture.requestWindow();
Enter fullscreen mode Exit fullscreen mode

We create a div element in the body of the pip window. On this div we will mount our Counter.js

const pipDiv = pipWindow.document.createElement("div");
pipDiv.setAttribute("id", "pip-root");
pipWindow.document.body.append(pipDiv);
Enter fullscreen mode Exit fullscreen mode

Now we mount our Counter.js component on the div with id “pip-root”.

const PIP_ROOT = ReactDOM.createRoot(
        pipWindow.document.getElementById("pip-root")
);
PIP_ROOT.render(<Counter />);

Enter fullscreen mode Exit fullscreen mode

Step 3 — Combining it all
The final MainComponent.js code should look something like this.

import React from "react";
import Counter from "./Counter";
import ReactDOM from "react-dom/client";

const MainComponent = () => {
 async function openPictureInPicture() {
  const pipWindow = await window.documentPictureInPicture.requestWindow();
  const pipDiv = pipWindow.document.createElement("div");
  pipDiv.setAttribute("id", "pip-root");
  pipWindow.document.body.append(pipDiv);
  const PIP_ROOT = ReactDOM.createRoot(pipWindow.document.getElementById("pip-root"));
  PIP_ROOT.render(<Counter />);
 }

 return (
  <div>
   <div onClick={openPictureInPicture}>Open counter</div>
  </div>
 );
};

export default MainComponent;
Enter fullscreen mode Exit fullscreen mode

Now we have our own react component mounting on a picture in picture window!

Top comments (0)