PDF viewer reloads the app and redirects to login when zooming on mobile browser - iOS
Author: mrunaljoshitdg8430-commitsCreated Sep 8, 2026Updated Sep 10, 2026
Labelsbug
### Before you start - checklist
- [x] I followed instructions in documentation written for my React-PDF version
- [x] I have checked if this bug is not already reported
- [x] I have checked if an issue is not listed in [Known issues](https://github.com/wojtekmaj/react-pdf/wiki/Known-issues)
- [x] If I have a problem with PDF rendering, I checked if my PDF renders properly in [PDF.js demo](https://mozilla.github.io/pdf.js/web/viewer.html)
### Description
import React, { useState, useRef, useEffect, useCallback } from 'react';
import { Document, Page, pdfjs } from 'react-pdf';
import { View } from 'react-native';
import FullscreenOverlayLoader from '../../sharedComponents/fullScreenLoader/FullscreenOverlayLoader';
import 'react-pdf/dist/Page/AnnotationLayer.css';
import 'react-pdf/dist/Page/TextLayer.css';
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
'pdfjs-dist/build/pdf.worker.min.mjs',
import.meta.url,
).toString();
const S = '[\\s.\\-\u2013\u2014]';
const PATTERNS = {
markdown: /\[([^\]]+)\]\(([^)]+)\)/g,
url: /https?:\/\/[^\s<>"{}|\\^`[\]]+/g,
email: /[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/g,
bareUrl: /(?"{}|\\^`[\]]*)?/g,
phone: new RegExp(
`(? {
if (typeof window === 'undefined') return 1;
return Math.min(window.devicePixelRatio || 1, 2);
};
const link = (href, text) => `${text}`;
const replaceOutsideTags = (html, regex, replacer) =>
html.split(/(]*>[\s\S]*?<\/a>)/gi)
.map((part, i) => {
if (i % 2 === 1) return part;
regex.lastIndex = 0;
return part.replace(regex, replacer);
})
.join('');
const resolveHref = (href, text) => {
const h = href.trim();
if (/^(tel|mailto):/.test(h)) return h;
if (/[<>]/.test(h)) {
const t = text.trim();
return /^https?:\/\//i.test(t) ? t
: /^[a-zA-Z0-9].*\.[a-zA-Z]{2,}/.test(t) ? `https://${t}`
: null;
}
return h;
};
// --- Optimized Lazy Page Component ---
const LazyPage = ({ pageNumber, initialWidth, renderText, zoomScale = 1 }) => {
const [isVisible, setIsVisible] = useState(false);
const [pageDimensions, setPageDimensions] = useState({ width: null, height: null });
const pageRef = useRef(null);
useEffect(() => {
let renderTimeout;
let observer;
if (typeof window !== 'undefined' && 'IntersectionObserver' in window) {
observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
renderTimeout = setTimeout(() => {
setIsVisible(true);
}, 250);
} else {
clearTimeout(renderTimeout);
setIsVisible(false);
}
},
{ rootMargin: isMobileBrowser ? '300px 0px' : '600px 0px' }
);
if (pageRef.current) {
observer.observe(pageRef.current);
}
} else {
setIsVisible(true);
}
return () => {
clearTimeout(renderTimeout);
if (observer) {
observer.disconnect();
}
};
}, []);
const onRenderSuccess = () => {
if (pageRef.current) {
setPageDimensions({
width: pageRef.current.offsetWidth,
height: pageRef.current.offsetHeight,
});
}
};
const baseDpr = getOptimalDpr();
const dpr = isMobileBrowser ? Math.min(baseDpr * zoomScale, 4) : baseDpr;
return (
{isVisible ? (
tags. */
customTextRenderer={renderText}
onRenderSuccess={onRenderSuccess}
/>
) : (
)}
)}
);
};
const PdfViewer = ({ fileDetails }) => {
const [numPages, setNumPages] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [pdfError, setPdfError] = useState(false);
const [initialWidth, setInitialWidth] = useState(null);
const [zoomScale, setZoomScale] = useState(1);
const pdfWrapper = useRef(null);
const setPdfSize = useCallback(() => {
if (pdfWrapper.current) {
setInitialWidth(pdfWrapper.current.offsetWidth - WIDTH_MARGIN);
}
}, []);
const throttle = (fn, ms = 300) => {
let active = false;
return (...args) => {
if (!active) {
active = true;
fn(...args);
setTimeout(() => { active = false; }, ms);
}
};
};
useEffect(() => {
setPdfSize();
const onResize = throttle(setPdfSize);
window.addEventListener('resize', onResize);
return () => window.removeEventListener('resize', onResize);
}, [setPdfSize]);
useEffect(() => {
if (!isMobileBrowser || typeof window === 'undefined' || !window.visualViewport) return;
let timeoutId;
const handleZoom = () => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
setZoomScale(window.visualViewport.scale || 1);
}, 300);
};
window.visualViewport.addEventListener('resize', handleZoom);
return () => {
clearTimeout(timeoutId);
window.visualViewport.removeEventListener('resize', handleZoom);
};
}, []);
const handleItemClick = ({ pageNumber }) => {
if (!pageNumber) return;
const targetElement = document.getElementById(`pdf-page-${pageNumber}`);
if (targetElement) {
targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
};
/* ✅ FIX 2: The `useEffect` that handled `handlePdfAnchorClick` has been entirely deleted.
This prevents the "WebKitBlobResource error 1" bug by letting Safari handle the tap naturally. */
const renderText = ({ str }) => {
try {
let s = str;
PATTERNS.markdown.lastIndex = 0;
s = s.replace(PATTERNS.markdown, (_, text, rawHref) => {
const href = resolveHref(rawHref, text);
return href ? link(href, text) : text;
});
s = replaceOutsideTags(s, PATTERNS.url, m => link(m, m));
s = replaceOutsideTags(s, PATTERNS.email, m => link(`mailto:${m}`, m));
s = replaceOutsideTags(s, PATTERNS.bareUrl, m => link(`https://${m}`, m));
s = replaceOutsideTags(s, PATTERNS.phone, m =>
link(`tel:${m.replace(/[\s.\-\u2013\u2014()]/g, '')}`, m)
);
return s;
} catch (e) {
console.error('[PdfViewer] renderText error:', e);
return str;
}
};
return (
<>
{isLoading && !pdfError && }
{pdfError && (
Failed to load the PDF. The file might be corrupted, or your network connection timed out.
{!pdfError && (
{
setNumPages(pageCount);
setIsLoading(false);
}}
onLoadError={(error) => {
console.error("PDF Load Error:", error);
setIsLoading(false);
setPdfError(true);
}}
loading=""
>
{Array.from({ length: numPages || 0 }, (_, i) => (
))}
)}
</>
);
};
export default PdfViewer;
above is code of pdfViewer.
Description :-
our web app is primarily based on PDF functionality, and users need to view and interact with PDFs as a core part of the application.
When the web app is opened in a mobile browser and a PDF is viewed, zooming in and zooming out on the PDF causes the application to reload. After the reload, the user is automatically redirected to the login screen.
Impact :-
Users are unable to smoothly view and zoom PDFs on mobile browsers, as the application reloads and requires them to log in again. and
### Steps to reproduce
1. Open the web app in a mobile browser.
2. Log in to the application.
3. Open any PDF using the PDF viewer.
4. Zoom in and zoom out on the PDF multiple times.
5. Observe the application behavior.
### Expected behavior
The PDF should allow the user to zoom in and zoom out without reloading the application or redirecting the user to the login screen and also text should be clear.
### Actual behavior
1. The web app reloads automatically.
2. The user is redirected to the login screen.
3. The PDF viewer is no longer displayed.
### Additional information
The issue occurs specifically when zooming in and zooming out on the PDF in the mobile browser. We have also tried different PDF viewer approaches, but the issue is still occurring.
### Environment
Device: Mobile device ( on web its working as expected )
Browser: Mobile Safari, chrome
react-pdf : "^10.2.0",
react: "19.1.0",
react-dom: "19.1.0",
react-native: "0.81.4",
Application: Web App
Issue: PDF ViewerSource: wojtekmaj/react-pdf