Skip to content

React ​

The viewer and the editor each fill an element you give them. In React, that's an element your component renders, and the viewer is created in it once React has put it on the page.

Install ​

sh
npm install @docmentis/udoc-viewer
sh
npm install @docmentis/udoc-editor

The component ​

tsx
import { useEffect, useRef } from "react";
import { UDocViewer } from "@docmentis/udoc-viewer";

/** A viewer filling its element, opening `src`. */
export function DocumentViewer({ src }: { src: string }) {
    const ref = useRef<HTMLDivElement>(null);
    useEffect(() => {
        let viewer: UDocViewer | undefined;
        // An effect that is cleaned up before `create` resolves, as StrictMode's
        // first run is, destroys the viewer it made.
        let gone = false;
        UDocViewer.create(ref.current!)
            .then(async (created) => {
                if (gone) return created.destroy();
                viewer = created;
                await viewer.open(src);
            })
            .catch((error: unknown) => console.error("The viewer didn't open the document:", error));
        return () => {
            gone = true;
            viewer?.destroy();
        };
    }, [src]);
    return <div ref={ref} className="pane" />;
}
tsx
import { useEffect, useRef } from "react";
import { UDocEditor } from "@docmentis/udoc-editor";

/** An editor filling its element, opening `src`. */
export function DocumentEditor({ src }: { src: string }) {
    const ref = useRef<HTMLDivElement>(null);
    useEffect(() => {
        let editor: UDocEditor | undefined;
        // An effect that is cleaned up before `create` resolves, as StrictMode's
        // first run is, destroys the editor it made.
        let gone = false;
        UDocEditor.create(ref.current!)
            .then(async (created) => {
                if (gone) return created.destroy();
                editor = created;
                await editor.open(src);
            })
            .catch((error: unknown) => console.error("The editor didn't open the document:", error));
        return () => {
            gone = true;
            editor?.destroy();
        };
    }, [src]);
    return <div ref={ref} className="pane" />;
}
  • The effect runs once the element is on the page, and creates the viewer in it. Its cleanup destroys the viewer.
  • create is asynchronous, so the cleanup can run before it resolves. In development, StrictMode mounts each component, unmounts it and mounts it again, which does exactly that. gone records it, and the viewer created after it is destroyed at once.
  • A new src runs the effect again, which destroys the viewer and creates another for the new document. To keep one viewer and open each new document in it, keep the viewer in a ref and call its open when src changes.

Use it ​

The viewer fills its element, so give the element a height, here through its pane class:

tsx
<DocumentViewer src="/report.pdf" />
css
.pane {
    height: 100vh;
}

The engine's files ​

Vite puts the engine's binary and fonts beside your app as it builds it, so there's nothing to set up. Quick start says where else they can come from.

The example ​

examples/react-vite shows the viewer and the editor side by side in a React app built with Vite.