最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Render a react component in a new window - Stack Overflow

programmeradmin4浏览0评论

I am developing a Certificate Management System where after all the processes have been done, the user may print a certificate.

I am struggling to implement such that upon clicking the print button, a new tab will open containing the ready to print HTML certificate so that the user will only CTRL + P to have the certificate printed.

How do i render my react certificate ponent in a new window? Such that i would only pass the props which are the data to be put into the certificate e.g., name, date etc.. like <Certificate name={john} />

I have tried implementing the npm react-new-window but it does not work with

<Button onclick={() => { 
<NewWindow>
  <CertificateComponent>
</NewWindow>
}}
>
PRINT BUTTON 
</Button>

I have looked into react portals but most use cases are for Modals, which is where my "PRINT" button is rendered.

Sorry for the bad english/explanation. Thank you!

I am developing a Certificate Management System where after all the processes have been done, the user may print a certificate.

I am struggling to implement such that upon clicking the print button, a new tab will open containing the ready to print HTML certificate so that the user will only CTRL + P to have the certificate printed.

How do i render my react certificate ponent in a new window? Such that i would only pass the props which are the data to be put into the certificate e.g., name, date etc.. like <Certificate name={john} />

I have tried implementing the npm react-new-window but it does not work with

<Button onclick={() => { 
<NewWindow>
  <CertificateComponent>
</NewWindow>
}}
>
PRINT BUTTON 
</Button>

I have looked into react portals but most use cases are for Modals, which is where my "PRINT" button is rendered.

Sorry for the bad english/explanation. Thank you!

Share Improve this question asked Jul 21, 2021 at 6:37 A SA S 431 silver badge8 bronze badges 3
  • 1 Have you looked this link: stackoverflow./questions/47574490/… – Majid M. Commented Jul 21, 2021 at 6:45
  • Have you tried this solution? stackoverflow./a/64391469/4831770 – Munei Nengwenani Commented Jul 21, 2021 at 6:48
  • 1 @MajidMohammadi Yes, but this question was asked 3 and a half years ago, i assume that there might be a newer or more efficient way to work around this problem. Thank you still! – A S Commented Jul 21, 2021 at 6:51
Add a ment  | 

4 Answers 4

Reset to default 2

New Solution based on CreatePortal

import React, { useEffect, useCallback, useMemo, useState } from "react";
import { render, createPortal } from "react-dom";

const App = () => {
  const [isOpen, setOpenState] = useState(false);
  const open = useCallback(() => setOpenState(true));
  const close = useCallback(() => setOpenState(false));

  return (
    <div>
      <h1>Portals in React</h1>
      <button onClick={open}>Open</button>
      <button onClick={close}>Close</button>
      {isOpen && (
        <NewWindow close={close}>
          Example <button onClick={close}>Close</button>
        </NewWindow>
      )}
    </div>
  );
};

const NewWindow = ({ children, close }) => {
  const newWindow = useMemo(() =>
    window.open(
      "about:blank",
      "newWin",
      `width=400,height=300,left=${window.screen.availWidth / 2 -
        200},top=${window.screen.availHeight / 2 - 150}`
    )
  );
  newWindow.onbeforeunload = () => {
    close();
  };
  useEffect(() => () => newWindow.close());
  return createPortal(children, newWindow.document.body);
};

render(<App />, document.getElementById("root"));

This worked for me with React 18.

    const secondaryWindow = window.open('', '_blank', 'width=600,height=400');
    secondaryWindow.document.open();

    secondaryWindow.document.write(`
    <html>
        <head>
            <title>My Title</title>
        </head>
        <body>
            <h2>My Header</h2>
            <div id="scheduling-grid"></div>
        </body>
    </html>
    `);

    const secondaryRoot = secondaryWindow.document.getElementById('scheduling-grid');

    const secondaryRootInstance = createRoot(secondaryRoot);

    secondaryRootInstance.render(<RelevantComponent prop={prop} />)

There can be multiple approaches for this.

Approach 1:

Create a new route and map the certificateComponent to it, make sure it doesn't have any authentication or any dependency to it.

Store the required data for certificateComponent either in session storage or local storage.

When the user clicks on print button, redirect the user to this new route using window.open("http://localhost:port/newroute").

In certificateComponent read the values stored in session/local storage and map it accordingly.

Approach 2:

Make the certificate ponent as an overlay which occupies the entire screen which shows up when the user click on print button. If any UI elements need to be hidden, you can do something as shown below:

printFn = function() {
    // show the certificate ponent 
    // hide the ui elements not required
    // window.print()
}

This worked for me

const myWindow: any = window.open('','', 'height: 500;width:500');
ReactDOM.render(<Yourponent prop={propValue} /> , myWindow.document.body);

myWindow.document.close();
myWindow.focus();
myWindow.print();
myWindow.close();
发布评论

评论列表(0)

  1. 暂无评论