[]
This tutorial shows how to integrate the Document Solutions for PDF Viewer (DsPdfViewer) into a React application using Vite. The DsPdfViewer lets users view and edit PDF files directly in the browser, including interactive PDF forms, and save modified documents on the client side. It supports all modern browsers and provides an efficient way to load and display PDF files in web applications.
Before you begin, make sure the following tools are installed:
Node.js (download the latest version from the official Node.js site)
NPM (included with Node.js)
A code editor, such as Visual Studio Code
Once these are installed, you can create and configure your React project.
Open a terminal and run the following command to create a new React application using Vite:
npm create vite@latest dspdfviewer-react -- --template reactDuring setup, you may be prompted to select a framework and variant. Select React as the framework and choose the variant that applies to your project. This tutorial uses JavaScript.

After the project is created, navigate to the project folder and install the required dependencies:
cd dspdfviewer-react
npm installYou can confirm that the project runs successfully with the following command:
npm run devThis starts the Vite development server and displays the default React application in the browser.
To add the PDF Viewer to your React project, install the @mescius/dspdfviewer package from npm:
npm install @mescius/dspdfviewerYou can also install Bootstrap for optional styling:
npm install bootstrapAfter installation, the library files will be available in:
node_modules/@mescius/dspdfviewer/

Open the index.html file and make sure the page includes a root element where the React application will be mounted:
<!-- index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DsPdfViewer | Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>Next, open main.jsx and remove StrictMode from the default React template. This helps avoid compatibility issues such as double mounting or duplicate viewer initialization during development.
// main.jsx
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<App />
)Update index.css so the application and viewer can fill the browser window:
/* index.css */
html,
body,
#root {
height: 100%;
margin: 0;
padding: 0;
}
#viewer {
width: 100%;
height: calc(100vh - 10px);
}Finally, replace the contents of App.jsx with the following code to initialize DsPdfViewer and add the default toolbar and sidebar panels:
// App.jsx
import { useEffect, useRef } from 'react';
import { DsPdfViewer } from '@mescius/dspdfviewer';
import 'bootstrap/dist/css/bootstrap.css';
import './App.css';
function App() {
const viewerRef = useRef(null);
useEffect(() => {
if (!viewerRef.current) {
console.error('Viewer container element not found');
return;
}
let viewer = null;
try {
viewer = new DsPdfViewer(viewerRef.current, {
workerSrc: './node_modules/@mescius/dspdfviewer/dspdfviewer.worker.js',
restoreViewStateOnLoad: false
});
viewer.addDefaultPanels();
} catch (error) {
console.error('Failed to initialize DsPdfViewer:', error);
}
return () => {
if (viewer) {
viewer.dispose();
}
};
}, []);
return <div id="viewer" ref={viewerRef}></div>;
}
export default App;The workerSrc option improves performance when rendering PDFs, and addDefaultPanels() adds the standard toolbar and navigation panels to the viewer.
Run the React application with the following command:
npm run devOnce the app builds, DsPdfViewer will display as an empty viewer in the browser window.

With the viewer running, you can load a PDF stored locally in your project. For this example, place a file named social_media_schedule.pdf in the public/pdfs/ folder.
To display the file automatically when the app starts, call the open() method after adding the default panels:
viewer.addDefaultPanels();
viewer.open('./pdfs/social_media_schedule.pdf');The full App.jsx file should look like this:
// App.jsx
import { useEffect, useRef } from 'react';
import { DsPdfViewer } from '@mescius/dspdfviewer';
import 'bootstrap/dist/css/bootstrap.css';
import './App.css';
function App() {
const viewerRef = useRef(null);
useEffect(() => {
if (!viewerRef.current) {
console.error('Viewer container element not found');
return;
}
let viewer = null;
try {
viewer = new DsPdfViewer(viewerRef.current, {
workerSrc: './node_modules/@mescius/dspdfviewer/dspdfviewer.worker.js',
restoreViewStateOnLoad: false
});
viewer.addDefaultPanels();
viewer.open('./pdfs/social_media_schedule.pdf');
} catch (error) {
console.error('Failed to initialize DsPdfViewer:', error);
}
return () => {
if (viewer) {
viewer.dispose();
}
};
}, []);
return <div id="viewer" ref={viewerRef}></div>;
}
export default App;When you run the application, the specified PDF file will load automatically in DsPdfViewer.

You can also use the openLocalFile() method to let users select a PDF through a native open-file dialog.
You can also open PDFs hosted on the same domain as your React application. Use the same open() method and provide the relative URL to the PDF:
viewer.open('/document-solutions/javascript-pdf-viewer/demos/product-bundles/assets/pdf/helloworld.pdf');The viewer will download and render the file directly in the browser. This method works for any PDF that resides within your web application’s domain.

When loading a PDF from a different domain, browsers may block the request due to CORS (Cross-Origin Resource Sharing) restrictions. To handle this, DsPdfViewer supports a SupportApi configuration, which uses an ASP.NET Core service as a proxy for loading and streaming remote PDF files.
In your ASP.NET Core project, add a controller named CorsProxyController:
[ApiController]
[Route("[controller]")]
public class CorsProxyController : ControllerBase
{
private readonly IHttpClientFactory _httpClientFactory;
public CorsProxyController(IHttpClientFactory httpClientFactory) => _httpClientFactory = httpClientFactory;
[HttpGet]
public async Task<IActionResult> Get(string url)
{
if (string.IsNullOrEmpty(url)) return BadRequest("Missing 'url' query parameter.");
var client = _httpClientFactory.CreateClient();
var response = await client.GetAsync(url);
if (!response.IsSuccessStatusCode) return StatusCode((int)response.StatusCode);
var stream = await response.Content.ReadAsStreamAsync();
var contentType = response.Content.Headers.ContentType?.ToString() ?? "application/pdf";
return File(stream, contentType);
}
}Register the HTTP client, controllers, CORS policy, and DsPdfViewer services in Program.cs:
// Add CORS
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
// Register HTTP client and controllers
builder.Services.AddHttpClient();
builder.Services.AddControllers();
GcPdfViewerHub.ConfigureServices(builder.Services);
var app = builder.Build();
// Use CORS with the custom policy
app.UseCors("AllowAll");
app.MapControllers();Once the proxy service is running, configure the supportApi object in your React viewer setup. Then call the open() method and pass in the proxy endpoint:
// App.jsx
import { useEffect, useRef } from 'react';
import { DsPdfViewer } from '@mescius/dspdfviewer';
import 'bootstrap/dist/css/bootstrap.css';
import './App.css';
function App() {
const viewerRef = useRef(null);
useEffect(() => {
if (!viewerRef.current) {
console.error('Viewer container element not found');
return;
}
let viewer = null;
try {
viewer = new DsPdfViewer(viewerRef.current, {
workerSrc: 'https://cdn.mescius.com/ds-pdfviewer/latest/dspdfviewer.worker.js',
restoreViewStateOnLoad: false,
supportApi: {
apiUrl: 'https://localhost:7126',
token: 'support-api-demo-net-core-token-2021',
webSocketUrl: false
}
});
viewer.addDefaultPanels();
viewer.open('https://localhost:7126/CorsProxy?url=https://cdn.mescius.io/sites/developer/legal/eula/ds/20250401-DOCUMENTS-EULA.pdf');
} catch (error) {
console.error('Failed to initialize DsPdfViewer:', error);
}
return () => {
if (viewer) {
viewer.dispose();
}
};
}, []);
return <div id="viewer" ref={viewerRef}></div>;
}
export default App;After these steps, your React app can securely open and render PDFs from external domains without encountering CORS errors.

Why doesn’t my PDF load when using a URL from another domain?
This is typically caused by browser CORS restrictions. To fix this, configure the supportApi option in DsPdfViewer to proxy remote file requests through your own server, such as an ASP.NET Core endpoint.
Can DsPdfViewer be used directly in a React application without a backend?
Yes. For local files, project assets, and same-domain URLs, no backend is required. A backend is only needed when loading files from external URLs that do not include the required CORS headers.
Does DsPdfViewer support editing or only viewing PDFs in React?
DsPdfViewer supports both viewing and editing features. Users can fill interactive forms, modify annotations, add comments, and save updated PDFs directly in the browser. Editing features require a Professional DsPdfViewer license and are not included in the standard DsPdfViewer license provided with every DsPdf license.
Why should StrictMode be removed from the React template?
React StrictMode may mount components more than once during development, which can cause the PDF Viewer to initialize twice. Removing StrictMode from this sample helps avoid duplicate initialization behavior while setting up DsPdfViewer.
Can DsPdfViewer work with frameworks other than React?
Yes. DsPdfViewer is framework-agnostic and works in React, Vue, Angular, or plain JavaScript/HTML applications. The API usage and configuration remain consistent across frameworks.