-
-
Notifications
You must be signed in to change notification settings - Fork 227
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
How to wait until content is loaded? #440
Comments
Hello. You'll want to use the If you are using class components instead this becomes much simpler, since you could replace This is a rough example, please let me know if you run into any trouble with it. const [dataLoaded, setDataLoaded] = useState(false);
const onBeforeGetContentResolve = useRef();
const componentRef = useRef();
const handleOnBeforeGetContent = () => {
return new Promise((resolve) => { // `react-to-print` will wait for this Promise to resolve before continuing
// Load data
onBeforeGetContentResolve.current = resolve;
setDataLoaded(true); // When data is done loading
});
};
const handlePrint = useReactToPrint({
content: () => componentRef.current,
onBeforeGetContent: handleOnBeforeGetContent,
});
useEffect(() => {
if (dataLoaded) {
// Resolves the Promise, telling `react-to-print` it is time to gather the content of the page for printing
onBeforeGetContentResolve.current();
}
}, [dataLoaded, onBeforeGetContentResolve]);
return (
<div>
<button onClick={handlePrint}>Print this out!</button>
<ComponentToPrint ref={componentRef} />
</div>
); |
HI Matthew
I understood your solution. I will give it a try.
Thanks for your help
Em qua., 8 de dez. de 2021 às 17:16, Matthew Herbst <
***@***.***> escreveu:
… Hello. You'll want to use the onBeforeGetContent callback and have it
return a Promise. This is a little tricky since you're waiting for React
state to update as well, and using hooks there is no easy way to know when
state is done updating, so you need to use the useEffect hook to check if
the state has updated.
If you are using class components instead this becomes much simpler, since
you could replace setDataLoaded(true); with this.setState({ dataLoaded:
true }, resolve) and not worry about the stuff in useEffect at all.
This is a rough example, please let me know if you run into any trouble
with it.
const [dataLoaded, setDataLoaded] = useState(false);const onBeforeGetContentResolve = useRef();const componentRef = useRef();
const handleOnBeforeGetContent = () => {
return new Promise((resolve) => {
// Load data
onBeforeGetContentResolve = resolve;
setDataLoaded(true); // When data is done loading
});};
const handlePrint = useReactToPrint({
content: () => componentRef.current,
onBeforeGetContent: handleOnBeforeGetContent,});
useEffect(() => {
if (dataLoaded) {
onBeforeGetContentResolve.current();
}}, [dataLoaded, onBeforeGetContentResolve]);
return (
<div>
<button onClick={handlePrint}>Print this out!</button>
<ComponentToPrint ref={componentRef} />
</div>);
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#440 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAGH5LIEGHY4KLHR45W6PVLUP64IPANCNFSM5JT5EV5Q>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
--
Marcos Cunha Lima
*Futura Tecnologia*
(11) 3864-9092
***@***.***
<http://www.futuranet.com.br>
|
Hi Matthew I thought that the const refImpressao = React.useRef()
const onBeforeGetContentResolve = React.useRef();
const [loaded, setLoaded] = React.useState(false)
const handleOnBeforeGetContent = () => {
return new Promise((resolve) => {
// Load data
console.log('set onBeforeContentResolve')
onBeforeGetContentResolve.current = resolve;
});
};
React.useEffect(() => {
if (loaded) {
console.log('loaded')
// as onBefore... is empty, it never runs this code
onBeforeGetContentResolve.current && onBeforeGetContentResolve.current();
}
}, [loaded, onBeforeGetContentResolve]);
const handleClick = useReactToPrint({
content: () => refImpressao.current,
onBeforeGetContent: handleOnBeforeGetContent
});
return (
<>
<div style={{ display: "none" }}>
<div ref={refImpressao}>
<ComponentToPrint setLoaded={setLoaded} />
</div>
</div>
<Button onClick={handleClick}>
Print
</Button>
</> It's hard to follow your example as the fetch logic is in the component being printed so I have to use a state variable to make this component alert when it loaded but the problem is that I don't understand when |
The const handleOnBeforeGetContent = () => {
return new Promise((resolve) => {
// Load data
// DO THIS! Load some data and/or make a change, and then change state to trigger a component re-render
console.log('set onBeforeContentResolve')
onBeforeGetContentResolve.current = resolve;
});
}; |
Yes, I change the loaded state (I pass a setLoaded to the right component which is loading asynchronously and sets this state when it's finished loading). Let's start again. I think this pattern is very common, you have a Component which you set a prop (Id) and it fetches the data asynchronously. const refImpressao = React.useRef()
const handleClick = useReactToPrint({
content: () => refImpressao.current,
});
return (
<>
<div style={{ display: "none" }}>
<div ref={refImpressao}>
<ComponentToPrint id={props.id}/>
</div>
</div>
<Button onClick={handleClick}>
Print
</Button>
</> This loads the data and shows up itself. It is used in lots of other places. I've put again in the simplest way just to help you or anybody else in order to come up with a new pattern which I am not seeing currently. |
Is it possible for you to share the code for the |
Hi Matthew I've created in codesandBox: ComponentToPrint It's a very contrived example. What I'm looking for is a "simple" way in order to make ReactToPrint wait for a finished component in order to print. Here is the code: import "./styles.css";
import { useReactToPrint } from "react-to-print";
import { useRef, useState, useEffect } from "react";
const ComponentToPrint = () => {
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
return setTimeout(() => {
setLoading(false);
}, 3000);
}, []);
const message = loading ? "loading" : "finished";
return <div> {message} </div>;
};
export default function App() {
const printRef = useRef();
const handleClick = useReactToPrint({
content: () => printRef.current
});
return (
<div className="App">
<h1>Print Test</h1>
<h2>with react-to-print</h2>
<div ref={printRef}>
<ComponentToPrint />
</div>
<button onClick={handleClick}> Print It </button>
</div>
);
} |
Ah, I see. There's no way for
|
Yes, the simplest solution is to add a callback and disable the button. Just to leave it registered: const ComponentToPrint = ({loading, setLoading}) => {
useEffect(() => {
let isCurrent = true;
setLoading(true);
const id = setTimeout(() => {
if (isCurrent) setLoading(false);
}, 3000);
return () => {
isCurrent = false;
clearTimeout(id);
};
}, []);
const message = loading ? "loading" : "finished";
return <div> {message} </div>;
};
export default function App() {
const printRef = useRef();
const [loading, setLoading] = useState(false);
const handleClick = useReactToPrint({
content: () => printRef.current
});
return (
<div className="App">
<h1>Print Test</h1>
<h2>with react-to-print</h2>
<div ref={printRef}>
<ComponentToPrint setLoading={setLoading} loading={loading}/>
</div>
<button onClick={handleClick} disabled={loading}> Print It </button>
</div>
);
} |
Hi
Is there a way to wait until all content is properly loaded in order to print?
I have a table which has a button in order to print the selected record.
I have a Form component which takes care of fetching some data, etc and that component returns what would be printed. While this component is fetching data, it shows a circular progress.
What is happening is that sometimes (when net is slow), the printing process shows this circular progress and not the finished component.
Thanks a lot for your very useful component.
The text was updated successfully, but these errors were encountered: