react-pdf-js
react-pdf-js copied to clipboard
Error when file parameter passed to usePdf is not a valid url
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