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-viewersh
npm install @docmentis/udoc-editorThe 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.
createis 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.gonerecords it, and the viewer created after it is destroyed at once.- A new
srcruns 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 itsopenwhensrcchanges.
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.