react-pdf-js icon indicating copy to clipboard operation
react-pdf-js copied to clipboard

Error when file parameter passed to usePdf is not a valid url

Open kairoswealth opened this issue 5 months ago • 0 comments

If we want to render pdf using a call to an API in the same component, we will always have the initialization state as undefined for the filename until we receive the actual file name for the API.

Though this can be handled gracefully in the JSX rendering, the hook itself will fail :

Invalid parameter object: need either .data, .range or .url at Module.getDocument (http://localhost:3000/static/js/vendors-node_modules_mui_icons-material_Launch_js-node_modules_react-player_lib_index_js-node-fe314d.chunk.js:4759:19)

If we try to initialize the usePdf conditionally, the hook fails again:

React Hook "usePdf" is called conditionally. React Hooks must be called in the exact same order in every component render

How can we handle such case without having to load a dummy pdf but instead by hiding the component?

Current code:

function Docs() {

    const [page, setPage] = useState(1);
    const canvasRef = useRef(null);
    const [isHovered, setIsHovered] = useState(false);
    const [selectedDocument, setSelectedDocument] = useState({})

    const docs = useSelector(state => state.dealRoom.selectedDeal)

    useEffect(() => {
        if (docs?.documents?.length > 0) {
            const firstDocument = docs.documents[0];
            setSelectedDocument(firstDocument);
        }
    }, [docs]);

    const handleClickSelectDocument = (index) => {
        const selectedDoc = docs?.document[index];
        if (selectedDoc) {
            setSelectedDocument(selectedDoc);
        }
    };

    const isValidUrl = (url) => {
        try {
            new URL(url);
            return true;
        } catch (_) {
            return false;
        }
    };

    // eslint-disable-next-line
    let { pdfDocument, pdfPage } = usePdf({
        file: selectedDocument.documentUrl,
        page,
        canvasRef,
    });


    const handlePrevious = () => setPage(page - 1);
    const handleNext = () => setPage(page + 1);

    return (
        <Grid id="Documents" sx={{ width: { xs: "100%", md: "calc(58% - 16px)", lg: "calc(66% - 16px)" }, backgroundColor: "white", border: "1px solid #ebebeb", borderRadius: "12px", paddingX: 2, paddingY: 1, display: "flex", flexDirection: "column" }}>
            {console.log({ selectedDocument })}
            <Typography sx={{ fontSize: "16px", fontWeight: "500", mb: 2 }}>Documents</Typography>
            {docs?.document?.length > 0 ?
                (<>
                    <Grid sx={{ display: "flex", flexDirection: "row", gap: 2, flexWrap: "wrap", mb: 1 }}>
                        {docs?.documents?.map((document, index) => {
                            return (
                                <Grid onClick={() => handleClickSelectDocument(index)} key={"document_" + index} sx={{ cursor: "pointer" }}>
                                    <Grid key={index} sx={{ display: "flex", flexDirection: "row", justifyContent: "centrer", alignItems: "center", border: document?.documentId === selectedDocument?.documentId ? "2px solid #643DD6" : "1px solid #ebebeb", borderRadius: "12px", paddingX: 2, paddingY: 1 }}>
                                        {document.documentType === "pdf" && <img src={PdfIcon} alt="pdf" />}
                                        <Typography sx={{ fontSize: "14px", fontWeight: "400", color: "#1e1e1e", ml: 1, fontStyle: "normal" }}>{document.documentDescription}</Typography>
                                    </Grid>
                                </Grid>
                            )
                        })}
                    </Grid>
                    <Grid
                        container
                        direction="column"
                        alignItems="center"
                        onMouseEnter={() => setIsHovered(true)}
                        onMouseLeave={() => setIsHovered(false)}
                        style={{ width: '100%', maxWidth: '600px', position: 'relative' }} // Adjust maxWidth as needed
                    >
                        {!pdfDocument && <span>Loading...</span>}
                        {pdfDocument &&
                            <canvas ref={canvasRef} style={{ width: '100%', height: 'auto' }} />
                        }
                        {Boolean(pdfDocument && pdfDocument.numPages) && (
                            <>
                                <Fade in={isHovered}>
                                    <OverlayControls>
                                        <OverlayButton
                                            disabled={page === 1}
                                            onClick={handlePrevious}
                                        >
                                            Prev
                                        </OverlayButton>
                                        <OverlayButton
                                            disabled={page === pdfDocument.numPages}
                                            onClick={handleNext}
                                        >
                                            Next
                                        </OverlayButton>
                                    </OverlayControls>
                                </Fade>
                            </>
                        )}
                    </Grid>
                </>) : (
                    <Typography sx={{ fontSize: "14px", fontWeight: "400" }}>No documents available</Typography>
                )
            }
        </Grid>
    )
}

export default Docs

kairoswealth avatar Sep 11 '24 07:09 kairoswealth