All Versions
Latest Version
Avg Release Cycle
20 days
Latest Release

Changelog History
Page 4

  • v2.4.2 Changes

    ๐Ÿ› Bug fixes

    • Can't delete the last remaining digit in the page number input
    • Properly check whether or not the fileUrl changes
    • ๐Ÿ‘€ Fix the issue where we see the spinner if the document has a single page and the height is smaller than the viewer's height
    • Can't open the downloaded file if it was loaded with Uint8Array
    • Annotation popup can be displayed under the previous or next page
    • When users download a document loaded with Uint8Array, the download file is named as document.pdf instead of the document blob
    • Clicking a bookmark doesn't jump to the destination properly in the first time if the bookmark also requires to zoom the document to fit the width

    ๐Ÿ‘Œ Improvements

    • Display the current page number in the right
    • Make the content of annotation scrollable
    • ๐Ÿ‘ Support shortcuts

    ๐Ÿ”Œ | Shortcut | Supported plugin | Action | | ----------------------------- | ---------------------------------------------------- | --------------------- | ๐Ÿ”Œ | cmd + p | Print | Print the document | ๐Ÿ”Œ | cmd + - | Zoom | Zoom out the document | ๐Ÿ”Œ | cmd + + | Zoom | Zoom in the document | ๐Ÿ”Œ | cmd + 0 | Zoom | Reset zoom to 100% |

  • v2.4.1 Changes

    ๐Ÿ› Bug fixes

    • Clicking the Download button doesn't work. It only works the file when scrolling to the second page
    • 0๏ธโƒฃ Using the Default Layout plugin, we can't scroll between pages on Safari 14
    • ๐Ÿ–จ The Open file button covers other elements, so we can't click on the Download or Print buttons. This issue only happens on Safari 14
  • v2.4.0 Changes

    ๐Ÿ†• New features

    • ๐Ÿ”Œ The Search plugin provides methods to search for given keywords programatically:
    Method Description
    clearHighlights Clear the highlights
    highlight Highlight multiple keywords
    jumpToNextMatch Jump to the next match
    jumpToPreviousMatch Jump to the previous match
    ๐Ÿ”Œ import { searchPlugin } from '@react-pdf-viewer/search';
    ๐Ÿ”Œ const searchPluginInstance = searchPlugin();
    ๐Ÿ”Œ const { clearHighlights, highlight, jumpToNextMatch, jumpToPreviousMatch } = searchPluginInstance;
    <button onClick={() => highlight(['document', 'PDF']) }>
        Highlight: document, PDF
    • ๐Ÿ’… It's possible to add custom styles for highlighted area based on the keyword:
    ๐Ÿ”Œ const searchPluginInstance = searchPlugin({
        onHighlightKeyword: (props: OnHighlightKeyword) => {
            if (props.keyword.source === 'document') {
       = '2px dashed blue';
       = 'rgba(0, 0, 0, .1)';
    • ๐Ÿ”Œ The Zoom plugin exposes the zoomTo function:
    ๐Ÿ”Œ const { zoomTo } = zoomPluginInstance;
    // Zoom to a given level
    • ๐Ÿ”Œ The Page Navigation plugin provides the jumpToPage function:
    ๐Ÿ”Œ const { jumpToPage } = pageNavigationPluginInstance;
    // Jump to the third page
    • It's possible to retrieve the instances of Attachment, Bookmark, Thumbnail, Toolbar plugins from the Default Layout plugin instance.
    0๏ธโƒฃ const defaultLayoutPluginInstance = defaultLayoutPlugin();
    const {
    0๏ธโƒฃ } = defaultLayoutPluginInstance;

    Similarity, the Toolbar plugin instance provides the accesses to the instance of other plugins that build the toolbar:

    ๐Ÿ”Œ const toolbarPluginInstance = toolbarPlugin();
    const {
    ๐Ÿ”Œ } = toolbarPluginInstance;

    ๐Ÿ‘Œ Improvements

    • ๐Ÿ‘Œ Support Next.js integration
    • ๐Ÿ›  Fix a warning in the Console when using with Next.js
    • ๐Ÿ”Œ The SingleKeyword type in the Search plugin supports flags:
    interface FlagKeyword {
        keyword: string;
        matchCase?: boolean;    // `false` by default
        wholeWords?: boolean;   // `false` by default
    type SingleKeyword = string | RegExp | FlagKeyword;

    You can use these flags when passing the keywords:

    ๐Ÿ”Œ const searchPluginInstance = searchPlugin({
        keyword: {
            keyword: 'document',
            matchCase: true,

    ๐Ÿ› Bug fixes

    • ๐Ÿ”Œ The Search plugin can find text that belongs to multiple span elements
    • ๐Ÿ›  Fix the type definitions of the MoreActionsPopover component in the Toolbar plugin

    ๐Ÿ’ฅ Breaking changes

    • ๐Ÿ“ฆ The Observer component is removed from the @react-pdf-viewer/core package
  • v2.3.2 Changes

    ๐Ÿ‘Œ Improvements

    • Lazy load the document. The PDF document will be loaded if the viewer container is visible in the viewport.

    ๐Ÿ› Bug fixes ๐Ÿ›  Fix a bug that could happen when we load multiple documents by changing fileUrl. ๐Ÿ‘€ In that case, you may see the error message

    • ๐Ÿ‘ท Worker was destroyed
    • Cannot read property 'sendWithPromise' of null

    ๐Ÿ›  This version also fixes a potential memory leaks reported by React DevTools when we try to load new document even if the current document isn't rendered completely.

  • v2.3.1 Changes

    ๐Ÿ‘Œ Improvements

    • ๐Ÿ”Œ full-screen plugin provides new callbacks that are triggered after entering and exiting the full screen mode
    import { SpecialZoomLevel } from '@react-pdf-viewer/core';
    import { fullScreenPlugin } from '@react-pdf-viewer/full-screen';
    const fullScreenPluginInstance = fullScreenPlugin({
        // Zoom to fit the screen after entering and exiting the full screen mode
        onEnterFullScreen: (zoom) => {
        onExitFullScreen: (zoom) => {

    ๐Ÿ› Bug fixes

    • ๐Ÿ’… The style files are missing in the highlight plugin
    • Render highlight annotations formed by quadrilaterals
    • The popup annotations aren't shown if they are children of highlight annotations
    • ๐Ÿ‘ป Clicking a destination (bookmark, for example) with name of FitH or FitBH throws an exception
  • v2.3.0 Changes

    ๐Ÿ†• New features

    • ๐Ÿ”Œ New highlight plugin provides the ability of selecting and adding notes for text in the document
    • 0๏ธโƒฃ The default-layout plugin allows to customize the tabs:
    // `defaultTabs` is the list of default tabs which lists thumbnails, bookmarks and attachments respetively
    const defaultLayoutPluginInstance = defaultLayoutPlugin({
        sidebarTabs: defaultTabs => { ... }

    We also can activate a given tab:

    const { activateTab } = defaultLayoutPluginInstance;
    // Activate a tab
    // activateTab(index);

    ๐Ÿ’ฅ Breaking changes

    • ๐Ÿ”Œ The getPagesRef method in plugins are changed to getPagesContainer:
    // Before
    interface PluginFunctions {
        getPagesRef(): React.RefObject<HTMLDivElement>;
    // After
    interface PluginFunctions {
        getPagesContainer(): HTMLElement;
    • ๐Ÿšš The authorization option is removed. You can use new withCredentials option:
    // Before v2.3.0
        authorization='Bearer ...'
    // From v2.3.0
            'Authorization': 'Bearer ...',
  • v2.2.1 Changes

    November 16, 2020

    ๐Ÿ‘Œ Improvements

    • Keep the current page and scroll position after zooming the document
    • ๐Ÿ‘€ Pre-render a few of previous and next pages of the current page, so users see the page instantly when scrolling
  • v2.2.0 Changes

    November 10, 2020

    ๐Ÿ†• New features

    • ๐Ÿ‘Œ Support loading PDF from a protected resource with new authorization option.
    import { Viewer } from '@react-pdf-viewer/core';
        authorization='Bearer ...'

    If you want to use another authorization servers or send more additional authentication headers, then use the new httpHeaders option, for example:

    import { Viewer } from '@react-pdf-viewer/core';
            key: value,
    • It's possible to customize the search control with the new Search component:
    import { RenderSearchProps, Search } from '@react-pdf-viewer/search';
        (renderSearchProps: RenderSearchProps) => (
            // Your custom search control

    ๐Ÿ— The parameter renderSearchProps provides the properties and methods to build up a custom search control:

    Property Type Description
    clearKeyword Function Clear the keyword
    changeMatchCase Function The result has to match case with the keyword
    changeWholeWords Function The result has to match the whole keyword
    currentMatch number The index of current match
    jumpToNextMatch Function Jump to the next match
    jumpToPreviousMatch Function Jump to the previous match
    keyword string The current keyword
    matchCase boolean true if the result matches case with the keyword
    wholeWords boolean true if the result matches the whole keyword
    search Function Perform the search with current keyword and matchCase, wholeWords conditions
    setKeyword Function Set the current keyword

    ๐Ÿ‘Œ Improvements

    • A current match search has a custom class rpv-search-text-highlight-current. So you can customize the current match by adding CSS properties for the class.
    • Avoid the black flickering when clicking a bookmark
    • ๐Ÿ‘Œ Support both React v16 and v17

    ๐Ÿ› Bug fixes

    • 0๏ธโƒฃ The print plugin doesn't work with default-layout plugin
    • ๐Ÿ–จ In some cases, there is an extra blank page when printing
    • ๐Ÿ”Œ Clicking bookmark doesn't jump to correct page in horizontal scroll mode
    • ๐Ÿ”Œ Jumping between search match doesn't work properly in horizontal scroll mode

    ๐Ÿ’ฅ Breaking changes

    • ๐Ÿšš The onCanvasLayerRender option is removed. Instead, use the onCanvasLayerRender option in your plugin.
    • The TextLayerRenderStatus enum is renamed to LayerRenderStatus.
  • v2.1.0 Changes

    October 27, 2020

    ๐Ÿ†• New features

    • ๐Ÿ”Œ Add onAnnotationLayerRender hook for plugin. We can perform custom action after annotations are rendered. The following sample code creates a plugin that finds all annotation links, and add the target="_blank" attribute to the links:
    import { AnnotationType, Plugin, PluginOnAnnotationLayerRender } from '@react-pdf-viewer/core';
    const customPlugin = (): Plugin => {
        const onRenderAnnotations = (e: PluginOnAnnotationLayerRender) => {
            // Find all `Link` annotation
                .filter((annotation) => annotation.annotationType === AnnotationType.Link)
                .forEach((annotation) => {
                    if (annotation.url) {
                        // Find the `a` element represents the link
                        [...e.container.querySelectorAll('.rpv-core-annotation-link a')].forEach((linkEle) => {
                            linkEle.setAttribute('target', '_blank');
        return {
            onAnnotationLayerRender: onRenderAnnotations,
    • ๐Ÿ”Œ The search plugin allows to set multiple keywords to be highlighted initially
    // Use the search plugin
    import { searchPlugin } from '@react-pdf-viewer/search';
    const searchPluginInstance = searchPlugin({
        keyword: ['document', 'PDF'],
    // Use with default-layout plugin
    import { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';
    const defaultLayoutPluginInstance = defaultLayoutPlugin({
        toolbarPlugin: {
            searchPlugin: {
                keyword: ['document', 'PDF'],

    ๐Ÿ‘Œ Improvements

    • โšก๏ธ Optimize the search plugin that doesn't perform unhighligting and highlighting many times after texts are rendered

    ๐Ÿ› Bug fixes

    • Clicking Previous match or Next match button throws an error if the keyword is empty
    • ๐Ÿ’… Fix the incorrect path of styles

    โฌ†๏ธ Upgrade from 2.0.1 to 2.1.0

    ๐Ÿ’… We have to update the path of styles which are placed in the lib directory. For example:

    // Old version
    import '@react-pdf-viewer/core/styles/index.css';
    // New version
    import '@react-pdf-viewer/core/lib/styles/index.css';
  • v2.0.1 Changes

    October 20, 2020

    ๐Ÿ”Œ This version rewrites the entire viewer with the plugin architecture. The main viewer component Viewer is very lightweight, ๐Ÿ”Œ and everything else is powered by plugins.

    The basic setup looks like following:

    // Import plugin
    import { toolbarPlugin } from '@react-pdf-viewer/toolbar';
    // Import styles
    import '@react-pdf-viewer/toolbar/lib/styles/index.css';
    // Create the plugin instance
    const toolbarPluginInstance = toolbarPlugin(...);
    // Register plugins
            // Array of plugins

    ๐Ÿ†• New features

    • 0๏ธโƒฃ Viewer supports to use a custom loader instead of the default <Spinner>:
    import { ProgressBar, Viewer } from '@react-pdf-viewer/core';
        renderLoader={(percentages: number) => (
            // You can use your own progress bar component
            <div style={{ width: '240px' }}>
                <ProgressBar progress={Math.round(percentages)} />
    • ๐Ÿ”Œ Customizable name of download file with the get-file plugin:
    const getFilePluginInstance = getFilePlugin({
        fileNameGenerator: (file: OpenFile) => {
            // `` is the URL of opened file
            const fileName ='/') + 1);
            return `a-copy-of-${fileName}`;
    • ๐Ÿ”Œ New Locale Switcher plugin for switching between different locales
    • ๐Ÿ”Œ Provide the ability of setting the scroll mode via the Scroll Mode plugin.

    ๐Ÿ› Bug fixes

    • The onPageChange could be invoked several times when clicking an outline item

    ๐Ÿ’ฅ Breaking changes

    • ๐Ÿšš The keyword option is removed. Use the keyword option provided by the search plugin.
    • ๐Ÿšš The layout option is removed
    • ๐Ÿšš The render option is removed
    • ๐Ÿšš The selectionMode option is removed. Use the selectionMode option provided by the selection-mode plugin.
    • ๐Ÿšš The onTextLayerRender option is removed. Instead, use the onTextLayerRender option in your plugin.

    โฌ†๏ธ Upgrade from 1.7.0 to 2.0.0

    ๐Ÿ“ฆ Uninstall the old packages:

    npm uninstall pdfjs-dist
    npm uninstall @phuocng/react-pdf-viewer

    ๐Ÿ“ฆ Install the new packages:

    npm install [email protected]
    npm install @react-pdf-viewer/[email protected]

    ๐Ÿ‘ท Replace the old `Worker` with new one:

    // Remove the old Worker
    import { Worker } from '@phuocng/react-pdf-viewer';
    // Use the new Worker
    import { Worker } from '@react-pdf-viewer/core';

    ๐Ÿ‘‰ Use the new Viewer:

    • 0๏ธโƒฃ First, you might need to install the Default Layout plugin:
    npm install @react-pdf-viewer/[email protected]
    • Replace the old Viewer with new one:
    // Old Viewer
    import Viewer from '@phuocng/react-pdf-viewer';
    // New Viewer
    import { Viewer } from '@react-pdf-viewer/core';
    // Plugins
    import { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';
    // Import styles
    import '@react-pdf-viewer/core/lib/styles/index.css';
    import '@react-pdf-viewer/default-layout/lib/styles/index.css';
    // Create new plugin instance
    const defaultLayoutPluginInstance = defaultLayoutPlugin();
    // Your render function
            // Register plugins