diegomura / react-pdf

📄 Create PDF files using React
https://react-pdf.org
MIT License
14.78k stars 1.17k forks source link

Support multiple layout passes (Pull request included) #899

Open rmmr opened 4 years ago

rmmr commented 4 years ago

I wanted to measure the height and width of my components through React refs and useEffect hook. Further more I wanted to modify the layout according to these measurements. This wasn't supported by react-pdf (v2).

I modified the reconciler and layout renderer to perform multiple passes, running at least 2 times, and at most N times comparing the previous layout to the final layout. Once these are equal it will render the actual PDF.

I also changed the Fractals example to showcase this usecase:

examples/fractals/Fractals.js

...
 const [bounds, setBounds] = useState(null);
  const ref = useRef();
  useEffect(() => {
    if (ref.current.prevBox !== undefined) {
      const { width, height } = ref.current.prevBox;
      if (bounds === null) {
        setBounds({ width, height });
      }
    }
  }, []);

  return (
    <View ref={ref} style={styles[direction]}>
      <Fractal direction={toggle(direction)} steps={steps - 1} />
      <View style={fractalStyle}>
        <Text style={styles.text}>
          {steps}
          {bounds !== null &&
            ` (${Math.round(bounds.width)}x${Math.round(bounds.height)})`}
        </Text>
      </View>
    </View>
  );
Screenshot 2020-05-12 at 12 42 18

The included pull request is the best implementation I could come up with. One major problem is the async nature of the layout renderer. I did not find a way to sync it with the reconciler in order to run it before every mount effect. That is why this solution creates a new container on every pass.

puchm commented 1 year ago

What is the state of this? It would be really helpful if it was possible to measure the components.