react-native-view-shot

Capture any React Native view and turn it into a PNG, JPG, WebP, or raw image, with native support for iOS, Android, and Windows.

Library
npm
v5.1.1
2,947stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
84/100Excellent
Development Activity96
Maintenance72
Community68
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
77/100Good
Architecture82
Code Quality85
Innovation62
Learning Curve80

react-native-view-shot lets a React Native app rasterize a live view hierarchy into an image file, a base64 string, or a data URI, either declaratively through a <ViewShot> wrapper component or imperatively through the captureRef(view, options) function. It ships native modules for iOS (via drawViewHierarchyInRect/renderInContext), Android (a custom ViewShot renderer with reusable bitmap and byte-buffer pools plus a raw/zip-base64 fast path that skips PNG/JPEG compression), and Windows (via UWP’s RenderTargetBitmap), unified behind one JS API. It fully supports React Native’s new architecture (Fabric + TurboModules) from v4.0 while remaining usable on the old architecture, so teams can adopt it mid-migration.

Beyond single-view capture it exposes captureScreen() for a full hardware screenshot of whatever is currently on screen, snapshotContentContainer to rasterize an entire ScrollView’s content rather than just the visible viewport, and releaseCapture(uri) to clean up temporary capture files. Common uses are share-to-social image generation, PDF/report thumbnails, watermarking user-generated content, and visual regression testing of RN screens. The library is a runtime dependency for apps but does not scaffold or own application structure — it is invoked from existing screens and components.

What You Get

  • A <ViewShot> wrapper component with captureMode set to mount, continuous, or update for automatic capture, or a ref-driven capture() call for manual capture
  • An imperative captureRef(view, options) function returning a Promise of the image URI, usable from anywhere a view ref is available
  • A captureScreen() API for a full hardware screenshot of the current screen on Android, iOS, and Windows without needing a specific view ref
  • Multiple output formats (png, jpg, webp, raw on Android) and result types (tmpfile, base64, data-uri, zip-base64) so callers can trade off speed, memory, and file handling
  • A raw + zip-base64 fast path on Android that skips PNG/JPEG compression entirely and instead deflate-compresses the ARGB pixel buffer, aimed at latency-sensitive continuous-capture use cases
  • Full support for both the old and new React Native architectures (Fabric/TurboModules) from v4.0 onward, so it works across a gradual migration

Common Use Cases

  • Generating a shareable image of a rendered chart, receipt, or profile card for social sharing or messaging
  • Producing thumbnails or watermarked exports of user-generated content composed from RN components
  • Capturing an entire scrollable view’s content (not just what’s visible) for PDF or report generation
  • Continuous or update-triggered capture for custom screen-recording or live-preview features
  • Visual regression testing by snapshotting rendered screens for comparison across builds

Under The Hood

Architecture The library exposes one small JS surface (src/index.tsx for the <ViewShot> component plus captureRef/captureScreen, backed by src/RNViewShot.ts and a codegen’d TurboModule spec in src/specs/NativeRNViewShot.ts) and delegates all real work to per-platform native modules: android/src/main/java/fr/greweb/reactnativeviewshot/{ViewShot,RNViewShotModule,RNViewShotPackage}.java implements Android capture with reusable bitmap/byte-array pools and a state machine (covered by dedicated JUnit tests such as ViewShotStateMachineTest, ProposeSizeTest, MarkSubtreeAlphaLayersTest), ios/RNViewShot.mm implements iOS capture via drawViewHierarchyInRect/renderInContext, and windows/ implements a UWP RenderTargetBitmap path with a documented capability gap (no full-scrollable-content capture). A RNViewShot.web.ts fallback lets captureRef work in web builds via html2canvas. The clean separation between the thin JS wrapper and self-contained platform implementations, each independently testable, is a deliberate layered design rather than a monolith.

Tech Stack Written in TypeScript (compiled via tsc, type-check run in CI as a strict gate), targeting React >=18 and React Native >=0.76 as peer dependencies, with html2canvas as the sole runtime dependency for the web fallback. Native code is Java/Kotlin-adjacent on Android, Objective-C++ on iOS, and C#/C++ under windows/ for UWP. The package is built with the standard RN TurboModule codegen (codegenConfig in package.json naming rnviewshot), and ships both CommonJS/ESM JS output (lib/) and a react-native entry (src/index.tsx) so bundlers pick the right one per environment.

Code Quality JS/TS logic is covered by Jest tests (captureRef.test.ts, validateOptions.test.ts, ViewShot.test.tsx, RNViewShot.web.test.ts) and native Android logic has its own JUnit suite under android/src/test, giving test coverage on both sides of the native bridge — a level of platform-parity testing many RN native modules skip. CI (ci.yml) runs Prettier format-check, tsc --noEmit, ESLint with --max-warnings 0, the Jest suite, and a separate Android APK build job, so regressions are caught before merge. TypeScript types are exported for all public options (CaptureOptions, ViewShotProperties), giving consumers compile-time safety around format/result string unions.

What Makes It Unique The raw image format combined with zip-base64 result type is a deliberate performance optimization most screenshot libraries don’t offer: it avoids PNG/JPEG (de)compression entirely on the native side, using zlib deflate instead of Android’s Bitmap.compress, with reusable bitmap and buffer pools to reduce GC pressure — aimed specifically at continuous/update capture modes where per-frame allocation cost matters. Combined with first-class new-architecture (Fabric/TurboModule) support well ahead of many comparable community modules, and an explicit, documented interoperability matrix noting exactly which platform/component combinations (WebView, gl-react, react-native-maps, react-native-svg) do and don’t capture correctly, it takes an unusually rigorous approach to a problem area (native view rasterization) that is often treated as an edge case.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search