React Image Viewer
react-viewer is a dedicated image viewing component for React applications, providing a customizable and feature-rich lightbox experience. It is currently in version 3.2.2 and sees active development with frequent minor releases addressing bugs and adding features. A major version 4.0 is planned to re-introduce Server-Side Rendering (SSR) support. Key differentiators include its native React implementation, utilizing React Hooks and `ReactDOM.createPortal` for modern React patterns, offering a robust alternative to general-purpose JavaScript viewer libraries like Viewer.js within a React ecosystem. It supports various image operations like zooming, rotating, scaling, and offers extensive customization through props for toolbar, navbar, and general UI behavior. It ships with TypeScript type definitions.
Common errors
-
Error: Invalid hook call. Hooks can only be called inside of the body of a functional component.
cause Using `react-viewer` v3.0.0 or later with an older version of React (pre-16.8.0).fixUpgrade `react` and `react-dom` packages to version `16.8.0` or higher. -
SyntaxError: Unexpected token 'export' (for ESM usage in Node.js/CJS environment)
cause `react-viewer` is primarily an ESM module for modern React projects, leading to issues when directly `require()`d in a CommonJS-only Node.js environment without proper transpilation or configuration.fixEnsure your project build setup (e.g., Webpack, Babel) correctly handles ESM modules, especially if targeting older Node.js versions or CommonJS. For client-side React apps, this is usually handled automatically. If running server-side, you might need to configure your bundler to transpile `node_modules`. -
The image viewer opens but appears unstyled or with incorrect layout.
cause Incorrect or missing CSS import, especially for `v3.2.0` where an external CSS import was temporarily required before reverting to CSS-in-JS.fixFor `react-viewer@3.2.0`, add `import 'react-viewer/dist/index.css';` to your entry point. For `v3.0.x` and `>=3.2.1`, this import is typically not needed, as styles are handled internally. Check the `react-viewer` release notes for your exact version to confirm CSS import requirements.
Warnings
- breaking Version 3.0.0 introduced significant breaking changes by refactoring with React Hooks and replacing `ReactDOM.unstable_renderSubtreeIntoContainer` with `ReactDOM.createPortal`. This requires React and React-DOM versions 16.8.0 or newer. Prior React versions are incompatible.
- breaking Server-Side Rendering (SSR) is not supported in any 3.x version of `react-viewer`. While version 3.2.0 attempted to re-enable SSR by extracting CSS, this was quickly reverted in 3.2.1 due to issues. Full SSR support is targeted for version 4.0.
- breaking The method of importing CSS changed between `v3.0.0`, `v3.2.0`, and `v3.2.1`. Version 3.0.0 moved to 'css-in-js', removing the need for an external CSS import. Version 3.2.0 re-extracted CSS requiring `import 'react-viewer/dist/index.css'`. Version 3.2.1 reverted to css-in-js, making the external import unnecessary again. This frequent change can cause styling issues.
Install
-
npm install react-viewer -
yarn add react-viewer -
pnpm add react-viewer
Imports
- Viewer
import { Viewer } from 'react-viewer';import Viewer from 'react-viewer';
- ViewerProps
import type { ViewerProps } from 'react-viewer'; - styles
import 'react-viewer/assets/index.css';
import 'react-viewer/dist/index.css';
Quickstart
import * as React from 'react';
import Viewer from 'react-viewer';
function App() {
const [visible, setVisible] = React.useState(false);
const images = [
{ src: 'https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_1280.jpg', alt: 'Forest' },
{ src: 'https://images.unsplash.com/photo-1507525428034-b723cf961c3e', alt: 'Beach' }
];
return (
<div>
<button onClick={() => { setVisible(true); } } style={{ padding: '10px 20px', fontSize: '16px', cursor: 'pointer' }}>
Show Images
</button>
<Viewer
visible={visible}
onClose={() => { setVisible(false); } }
images={images}
activeIndex={0}
downloadable={true}
zoomable={true}
rotatable={true}
scalable={true}
noFooter={false}
/>
</div>
);
}