react-pdf-viewer v3.1.0 Release Notes

  • ๐Ÿ†• New features

    • โœ… Add new testId property to Spinner
    • The Viewer component provides new scrollMode option:
    import { ScrollMode, Viewer } from '@react-pdf-viewer/core';
    
    <Viewer scrollMode={ScrollMode.Horizontal} />;
    
    • ๐Ÿ”Œ Plugins can register and call the switchScrollMode method to switch the scroll mode programatically

    ๐Ÿ‘Œ Improvements

    • The Viewer component now works on mobile.

    ๐Ÿ’ป As we know, the mobile browsers such as iOS Safari have the limit value for canvas size and the maximum memory values (256 MB on iOS Safari, for example) for rendering canvases. ๐Ÿ›  It can cause the Viewer component to crash if we zoom the document to a big enough level. This version fixes these kinds of issues. There is no crash on mobile anymore!

    • ๐ŸŽ Improve the performance when rendering a document.

    0๏ธโƒฃ In the previous versions, each page is represented by a separated div element. The element isn't rendered by default, and will be rendered when the corresponding page is visible in the viewport. However, this optimization is not enough for a document that has a big number of pages.

    v3.1.0 brings the optimization to a new level. Instead of keeping the instance of all pages all the time, the Viewer component only renders a given range of pages including the visible pages and some pages that are before and after them. ๐Ÿ‘€ For example, if users see pages 5-8 in the screen, we will render the pages 3-10 ony. The range will be changed when users scroll up or down, and then the corresponding pages are rendered accordingly.

    ๐Ÿ› Bug fixes

    • Keep the current page after switching the scroll mode
    • The Cover component has the same image source when loading different documents
    • 0๏ธโƒฃ The default Spinner is used when using the renderLoader option
    • The exit full screen button doesn't look good in dark theme
    • The onPageChange event fires more than once
    • The renderThumbnailItem option doesn't work with dynamic document
    • The sidebar doesn't fit in its container on Safari
    • There is a black area in the full screen mode if the zoom level is small enough

    ๐Ÿ’ฅ Breaking changes

    • ๐Ÿšš It is not possible to access the page element in a plugin with the getPageElement function. The method is removed because the pages are rendered dynamically
    • ๐Ÿ“ฆ The ScrollMode provided by the @react-pdf-viewer/scroll-mode package now belongs to the @react-pdf-viewer/core package:
    // v3.0.0 and previous versions
    import { ScrollMode } from '@react-pdf-viewer/scroll-mode';
    
    // From v3.1.0
    import { ScrollMode } from '@react-pdf-viewer/core';
    
    • ๐Ÿ”Œ The inital scroll mode option provided by the scrollModePlugin plugin now belongs to the Viewer component:
    // v3.0.0 and previous versions
    import { scrollModePlugin, ScrollMode } from '@react-pdf-viewer/scroll-mode';
    
    const scrollModePluginInstance = scrollModePlugin({
        scrollMode: ScrollMode.Horizontal,
    });
    
    // From v3.1.0
    import { ScrollMode } from '@react-pdf-viewer/core';
    
    <Viewer scrollMode={ScrollMode.Horizontal} />;
    
    • ๐Ÿ’… There aren't CSS styles provided by the @react-pdf-viewer/scroll-mode package:
    // v3.0.0 and previous versions
    import '@react-pdf-viewer/scroll-mode/lib/styles/index.css';
    
    // From v3.1.0
    // Remove the import above
    
    • From v3.1.0, pages are rendered one by one. If you use a custom page renderer, then you have to call the markRendered method to mark the page rendered completely. Hence the next page in the queue will be rendered.
    // v3.0.0 and previous versions
    import type { RenderPageProps } from '@react-pdf-viewer/core';
    
    const CustomPageRender: React.FC<{
        renderPageProps: RenderPageProps,
    }> = ({ renderPageProps }) => {
        return (
            <>
                {/* Use the canvas and/or text layers */}
                {renderPageProps.canvasLayer.children}
                {renderPageProps.textLayer.children}
    
                {/* Your custom components on page ... */}
            </>
        );
    };
    
    <Viewer renderPage={(props) => <CustomPageRender renderPageProps={props} />} />;
    
    // From v3.1.0
    const CustomPageRender: React.FC<{
        renderPageProps: RenderPageProps,
    }> = ({ renderPageProps }) => {
        React.useEffect(() => {
            if (renderPageProps.canvasLayerRendered && renderPageProps.textLayerRendered) {
                renderPageProps.markRendered(renderPageProps.pageIndex);
            }
        }, [renderPageProps.canvasLayerRendered, renderPageProps.textLayerRendered]);
    
        return (
            <>
                {/* Use the canvas and/or text layers */}
                {renderPageProps.canvasLayer.children}
                {renderPageProps.textLayer.children}
    
                {/* Your custom components on page ... */}
            </>
        );
    };
    
    <Viewer renderPage={(props) => <CustomPageRender renderPageProps={props} />} />;