React-to-print: Refs are not available for stateless components. For 'react-to-print' to work only Class based components can be printed

Created on 13 Feb 2019  路  9Comments  路  Source: gregnb/react-to-print

Most helpful comment

Add my thanks to @MarkNewcomb1. The above information is useful. I met the same problem to print non-class-based component and I finally got it to work by putting the component as the child of <div ref={componentRef} />.

All 9 comments

What part of that error message do you need help with?

This's an alternative for stateless component:

import React, { useRef } from 'react';
import ReactToPrint from 'react-to-print';

class ComponentToPrint extends React.PureComponent {
  render() {
    return (
      <table>
        <thead>
          <th>column 1</th>
          <th>column 2</th>
          <th>column 3</th>
        </thead>
        <tbody>
          <tr>
            <td>data 1</td>
            <td>data 2</td>
            <td>data 3</td>
          </tr>
        </tbody>
      </table>
    );
  }
}

const Example = () => {
  const componentRef = useRef();
  return (
    <div>
      <ReactToPrint
        trigger={() => <button>Print this out!</button>}
        content={() => componentRef.current}
      />
      <ComponentToPrint ref={componentRef} />
    </div>
  );
};
export default Example;

@andydev404 hooks 馃挴

Something worth noting: the component you want to print will still need to be a class component. If Example _AND_ ComponentToPrint are both non-class-based, it won't work. I had trouble with this this morning, where in my example, Example was a functional, stateless component and ComponentToPrint was also a functional, stateless component. I kept getting this Refs are not available for stateless components error when clicking on my print link. Taking this error message quite literally, I tried converting my ComponentToPrint to a stateful component using useState while still keeping it a functional component.

Turned out that wasn't good enough. It's not necessarily that it's a stateless component. It's that it's not a _class based component_.

Interestingly, in my wrestling with this, I tried <h1 ref={componentRef}>HELLO?</h1> and that worked - even though a simple h1 tag is certainly not a class based component.

Thanks for the information @MarkNewcomb1 we may need to update our error messages in the hooks world, since previously a functional component had no effective way of maintaining state.

Add my thanks to @MarkNewcomb1. The above information is useful. I met the same problem to print non-class-based component and I finally got it to work by putting the component as the child of <div ref={componentRef} />.

If one wants to just have functional components, they can refer to the below example:

import React, { useRef } from "react";
import ReactToPrint from "react-to-print";

const ComponentToPrint = React.forwardRef((props, ref) => (
      <table ref={ref}>
        <thead>
          <th>column 1</th>
          <th>column 2</th>
          <th>column 3</th>
        </thead>
        <tbody>
          <tr>
            <td>data 1</td>
            <td>data 2</td>
            <td>data 3</td>
          </tr>
          <tr>
            <td>data 1</td>
            <td>data 2</td>
            <td>data 3</td>
          </tr>
          <tr>
            <td>data 1</td>
            <td>data 2</td>
            <td>data 3</td>
          </tr>
        </tbody>
      </table>
));

const Example = () => {
    const componentRef = useRef();
    return (
      <div>
        <ReactToPrint
          trigger={() => <a href="#">Print this out!</a>}
          content={() => componentRef.current}
        />
        <ComponentToPrint ref={componentRef} />
      </div>
    );
}

export default Example;

I got the correct answer with the following solution and bypassed this error

import React, { useRef } from "react";
import ReactToPrint from "react-to-print";

export default function PrinterWrapper({ children }) {
    const linkToPrint = () => {
        return (
            <button>Click To PrintOF Body</button>
        )
    }
    const componentRef = useRef();
    return (
        <>
            <ReactToPrint trigger={linkToPrint} content={() => componentRef.current} />
            <div ref={componentRef}>
                {children}
            </div>
        </>
    );
}

I followed the examples given and still get the error message. Could it be because the wrapped component has some stateless components in it?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ishan7 picture ishan7  路  3Comments

hoangdoan267 picture hoangdoan267  路  8Comments

jermsam picture jermsam  路  7Comments

Dastnbek picture Dastnbek  路  4Comments

jogoool picture jogoool  路  8Comments