skip to Main Content

I am trying to find the width of a p element in order to dynamically set the width of the PDF using react-pdf/renderer. Currently, when I hit the button to print the width to console, I get the same number each time and it does not change no how long or short the input is. What am I missing?

  const Preview = (props) => {
  const ref = useRef();
  const [width, setWidth] = useState(0);

  useEffect(() => {
    setWidth(ref.current.offsetWidth);
    };
  });

  const MyDoc = () => {
    Font.register({
      family: "broadsheet",
      src: broadsheet,
    });
    Font.register({
      family: "jost",
      src: jost,
    });
    Font.register({
      family: "texgyreheros",
      src: texgyreheros,
    });
    return (
      <Document>
        <Page
          size={[20000, 20000]}
          style={{
            fontFamily: props.pdfFont,
            fontSize: props.size,
          }}
        >
          <View style={{ margin: "auto", lineHeight: "0" }}>
            <Text>{props.preview}</Text>
          </View>
        </Page>
      </Document>
    );
  };

  const getDimHandler = (e) => {
    e.preventDefault();

    console.log(width);
  };

  return (
    <>
      <Container className="bg-white p-5 mb-5">
        <p className={`${props.font} text-[8rem]`}>{props.preview}</p>
      </Container>

      <p ref={ref} id={props.sizeClass} className={`${props.font}`}>
        {props.preview}
      </p>

      <PDFDownloadLink
        document={<MyDoc />}
        fileName="somename.pdf"
        className="bg-violet-500 hover:bg-violet-700 text-white font-bold py-2 px-4 rounded-full"
      >
        {({ blob, url, loading, error }) =>
          loading ? "Preparing document..." : "Download"
        }
      </PDFDownloadLink>
      <button onClick={getDimHandler}>Get Dims</button>
    </>
  );
};

export default Preview;

2

Answers


  1. To ensure that the effect runs only when the component mounts or when the ref changes,by putting empty array dependency

    useEffect(() => {
          setWidth(ref.current.offsetWidth);
      }, []);
    
    Login or Signup to reply.
  2. You can create a custom hook like this:

    const useResize = (myRef) => {
      const [width, setWidth] = useState(0)
      const [height, setHeight] = useState(0)
      
      const handleResize = useCallback(() => {
          setWidth(myRef.current.offsetWidth)
          setHeight(myRef.current.offsetHeight)
      }, [myRef])
    
      useEffect(() => {
        window.addEventListener('load', handleResize)
        window.addEventListener('resize', handleResize)
    
        return () => {
          window.removeEventListener('load', handleResize)
          window.removeEventListener('resize', handleResize)
        }
      }, [myRef, handleResize])
    
      return { width, height }
    }
    

    and then you can use it like:

    const MyComponent = () => {
      const componentRef = useRef()
      const { width, height } = useResize(componentRef)
    
      return (
        <div ref={componentRef }>
          <p>width: {width}px</p>
          <p>height: {height}px</p>
        <div/>
      )
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search