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

Can the "ComponentToPrint" be a functional component? #181

Closed
devans-k4 opened this issue Nov 26, 2019 · 10 comments
Closed

Can the "ComponentToPrint" be a functional component? #181

devans-k4 opened this issue Nov 26, 2019 · 10 comments
Labels

Comments

@devans-k4
Copy link

I see in the documentation an example that calls from a functional component so I see the library has been updated with hooks but I'm curious if there is a current way to have the print component be a functional component as well.

The console error I receive is
"Refs are not available for stateless components. For "react-to-print" to work only Class based components can be printed "

so I guess this just isn't an option?

@MatthewHerbst
Copy link
Owner

Not sure what you saw, but this library does not use hooks, which is the reason we cannot currently support functional components. To use hooks would require bumping the React peerDependency, which would be a breaking change.

@devans-k4
Copy link
Author

Oh whoops I had misunderstood. Thanks for the response and very useful library!

@vjsingh
Copy link

vjsingh commented Dec 5, 2019

@MatthewHerbst Are there plans to support functional components?

@MatthewHerbst
Copy link
Owner

@vjsingh eventually. Doing so would require bumping our React peer dependency, which would be a breaking change. Since there's no use-case that I know of where someone can't use class based components at all, it's unlikely we'll bump that dependency anytime soon unless there is some other feature/bug that requires a breaking change.

@vjsingh
Copy link

vjsingh commented Dec 6, 2019

@MatthewHerbst I see, that makes sense and seems like a good policy for the library. Good work!

For myself I created a new PrintableComponent which takes in a view (which can be a functional component), wraps it in a <View/> and then uses that as the component to pass to react-to-print. Seems to be working just fine and lets me use functional components.

@AaronMinnamon
Copy link

AaronMinnamon commented Dec 6, 2019

@vjsingh Could you post example code of how you are setting up your PrintableComponent? I am trying to do this exact thing right now.

@vjsingh
Copy link

vjsingh commented Dec 6, 2019

@AaronMinnamon Hope this helps

import * as React from 'react';
import { View } from 'react-native';
import ReactToPrint from 'react-to-print';
import PrintableGrid from 'src/web/Cards/PrintableGrid';
import RouteCard from 'src/web/Cards/RouteCard';
import Tile from 'src/web/Components/Tile';

interface InputProps {
  displayView: JSX.Element;
  PrintView: () => JSX.Element;
}

const PrintableComponent: React.FC<InputProps> = props => {
  const componentRef = React.useRef();

  return (
    <>
      <ReactToPrint
        trigger={() => props.displayView}
        content={() => componentRef.current}
      />
      <View style={{ display: 'none' }}>
        <View ref={componentRef}>
          <props.PrintView/>
        </View>
      </View>
    </>
  );
}

export default PrintableComponent;

@AaronMinnamon
Copy link

@vjsingh Perfect thank you!

Now if I could only figure out why my mobile styles are showing up in the print dialog window...

@BossBele
Copy link

To add on @vjsingh 's answer.
Another trick is to pass a prop with the ref to the imported component.

Example:
Code in Print.js file:

import React, { useRef, Component } from 'react'
import ReactToPrint from 'react-to-print';
import Showprint from './showprint.js'

  export default()=>{
    const componentRef = useRef();
      return (
        <div>
          <ReactToPrint
            trigger={() => <a href="#">Print this out!</a>}
            content={() => componentRef.current}
          />
          <Showprint refPropWithAnotherName={componentRef} />
        </div>
      );
  }

Code in showprint.js file:

import React,{Component} from 'react'

export default Showprint ({refPropWithAnotherName})=> {
    return(
        <div ref={refPropWithAnotherName}>
        <p>hello</p>
        </div>
    );
}

WORKS LIKE MAGIC

@rivaslive
Copy link

rivaslive commented Apr 6, 2021

Although @BossBele's solution seems to be good It seems only works with HTML elements and not react components, when you have a complex component or styled-component it is not able to pass the alert, my solution is to simply create a class-based HOC that renders a functional component

const Print = ({ okText, children, ...rest }) => {
	const dashboardRef = useRef();
	let nestChild = children;
	let printButton = okText;
	
	if (typeof children === "string") {
		nestChild = <span>{children}</span>;
	}
	if (typeof okText === "string") {
		printButton = <span>{okText}</span>;
	}
	
	return <>
		<ReactToPrint
			trigger={() => okText ? printButton :
				<ButtonComponent className="a-btn--linkYellowBottom" text="despegar reporte" />}
			content={() => dashboardRef.current}
			documentTitle="example--document.pdf"
		/>
		
		<HOCView ref={dashboardRef}>
			{React.cloneElement(nestChild, { ...rest })}
		</HOCView>
	</>;
};

class HOCView extends Component {
	render() {
		return <HOCViewStyle>
			{this.props.children}
		</HOCViewStyle>;
	}
}

Print.propTypes = {
	children: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
	okText: PropTypes.oneOfType([PropTypes.node, PropTypes.string])
};


export default Print;

Styled HOC component, the component is hidden until print is launched in the browser

import styled from "styled-components";

export const HOCViewStyle = styled.div`
	display: none;
	@media print {
		display: block;
	}
`

the way it is used is as follows:

const  App = () => {
    return  <div>
        <Print>
              <p>Render any children</p>
	</Print>
    </div>
}

The result is a button that will display the content (children) until it is pressed

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

No branches or pull requests

6 participants