Library / SDK
syanbo/react-native-syan-image-picker avatar
syanbo/react-native-syan-image-picker

react-native-syan-image-picker wraps two native pickers for React Native

React-Native 多图片选择 支持裁剪 压缩

631 stars157 forksJavaMIT

At a glance

What is it?
react-native-syan-image-picker is a React Native module that puts a multi image picker in front of PictureSelector on Android and TZImagePickerController on iOS, with cropping, compression, base64 output and a long list of platform specific switches that the README documents in detail.
Who is it for?
react-native-syan-image-picker fits a React Native team that needs multi selection with cropping and compression and does not want to write the native bridge for both platforms, and that is prepared to maintain the platform configuration it documents.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A thin layer over two established native pickers

react-native-syan-image-picker is described as a multi image selection component for React Native apps, built by wrapping existing native third party frameworks, with cropping and compression support. The description in the package metadata is the same in Chinese: a React Native multi image picker that supports cropping and compression.

The native dependencies are named, and each is credited to its author. On Android it is PictureSelector by LuckSiege, and on iOS it is TZImagePickerController by banchichen. That is the essential design decision of the project, and it has consequences in both directions.

In the positive direction, the picker behaviour, the camera integration and the gallery UX come from two projects that have had their own development, rather than being reinvented in a React Native bridge. The module is the glue, and the glue is the part you can read.

In the other direction, the module inherits those projects' constraints and their version requirements, which is where most of the README's length goes. The Android side needs a specific minSdkVersion because of PictureSelector, the iOS side needs a bundle resource copied into the Xcode target, and both sides need their own permission declarations. A React Native library that is not a single self-contained implementation is a library whose upgrade path is a negotiation between three version numbers.

The audience is a React Native developer who wants a picker on both platforms without maintaining two native modules.

What the options actually control

The component takes an options object, and the README documents the properties with their types, whether they are optional, their defaults and their meaning. The list is long, and a few entries are worth calling out because they are the ones that change behaviour in ways a developer cannot guess.

The first is that cropping only works when imageCount is 1. The isCrop option defaults to false, and the note says it takes effect only when the image count is one. The crop geometry is controlled by CropW and CropH, both defaulting to 60 percent of the screen width, and showCropCircle switches on a circular crop area with circleCropRadius defaulting to half the screen width. showCropFrame controls whether the crop area is drawn and showCropGrid controls the grid inside it.

The second is the compression set. compress defaults to true, and the note says that with compression off some image properties cannot be obtained. quality is the compression quality, defaulting to 90, and the note says it has no effect on Android, where a fixed compression is used. minimumCompressSize defaults to 100 and means images below 100 kilobytes are not compressed on Android, and compressFocusAlpha keeps the alpha channel when compressing, at the cost of a larger PNG.

The third is the GIF caveat. isGif defaults to false and allows selecting GIFs, but the note says there is currently no callback for GIF data, so a GIF can be picked and then arrive without its animation payload.

The rest are switches worth knowing about: enableBase64 returns base64 encoded images and defaults to false, isRecordSelected keeps track of the currently selected images, isCamera allows the user to take a photo inside the picker and defaults to true, showSelectedIndex shows the selection order, and freeStyleCropEnabled, rotateEnabled and scaleEnabled are marked as Android behaviours for the crop frame.

Installation and the linking step that has aged

The install is an npm or yarn add, followed by a linking command:

bash
npm install react-native-syan-image-picker --save
bash
yarn add react-native-syan-image-picker
bash
react-native link react-native-syan-image-picker

The linking step is where the age of the project shows. The react-native link command was the mechanism for wiring native modules before automatic linking, and the README carries a whole section on manual linking for React Native versions below 0.60, covering the Xcode side with the Libraries group and libRNSyanImagePicker.a, and the Android side with the import of the package class, the instance added to getPackages(), the include line in settings.gradle and the project dependency in build.gradle.

The README also notes that for React Native 0.60 and later the CocoaPods setup means the manual bundle configuration is not needed, which tells you the configuration steps in the documentation were written for the pre-autolinking era and have not been reorganised since.

The package metadata shows how the module is laid out for consumers. The main entry is src/index.js, the types come from src/index.d.ts, and the files array publishes only src, ios, android, the podspec, the licence, the readme and the changelog, so the example application is not shipped. The package is published to npm under the name react-native-syan-image-picker, and there is a podspec, RNSyanImagePicker.podspec, at the root for the iOS side.

iOS configuration: bundle resource, permissions, localisation

The iOS side has four configuration steps, and the first one is the resource copy that older React Native versions still need.

The TZImagePickerController bundle has to be added to the target. In Xcode that means selecting the project, going to TARGETS and Build Phases, then Copy Bundle Resources, clicking the plus button, choosing Add Other and pointing at the bundle inside node_modules at the TZImagePickerController path. The README notes that React Native 0.60 and later use CocoaPods and do not need this step.

The second step is permissions. Four Info.plist keys have to be added to the project, and they are the camera usage description, the photo library usage description, the photo library additions usage description, and a location when in use usage description. The last one is the surprise, since a picker for images does not obviously need location, and the README presents it as one of the strings to add.

The third step is localisation, adding Chinese (Simplified) to the project localizations list, which the README labels as Chinese adaptation.

The fourth step is dependency freshness, and it is a single command:

bash
pod update TZImagePickerController

That step matters because the iOS picker is an external pod, and the version CocoaPods resolves is not the version the module was tested against unless you update it deliberately. This is the recurring theme of the whole installation section: the module is only as predictable as the state of the native projects underneath it.

Android configuration: permissions, minSdkVersion and runtime requests

Android has three permissions to declare in the manifest:

xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />

Then the minimum SDK has to be raised, because PictureSelector needs it. The README gives the change in the app build.gradle:

gradle
// app/build.gradle

android {
    minSdkVersion = 19
    ...
}

The third step is that runtime permissions have to be requested before taking a photo, and the README supplies a JavaScript example that calls PermissionsAndroid.request for the write external storage permission with a title, a message and the three button labels, then checks the result against PermissionsAndroid.RESULTS.GRANTED. The example carries a joking message string, and the point of it is the shape of the call rather than the wording, since the permission has to be granted at runtime on modern Android rather than only declared in the manifest.

The final configuration note is about troubleshooting. If the app fails to install or run, the README asks you to check whether autolinking succeeded, to look in MainApplication.java in Android Studio to see whether the RNSyanImagePickerPackage instance was added, and to open the project in Android Studio to confirm that Gradle synchronised. The last of those is the one worth remembering, because a Gradle sync failure produces symptoms that look like a code problem.

Two documented conflicts with other popular modules

The README devotes two sections to conflicts with other React Native libraries, and this is the most practically useful part of the document for anyone who already has a media stack in place.

The first conflict is with fast-image. If you use fast-image at the same time, the README says to set the glideVersion in the buildscript ext block of build.gradle to the same version as the one fast-image uses, and to add a pictureVersion entry for a custom picture_library version. Two image libraries in one app, each with its own image loading and caching expectations, is the kind of combination that produces subtle rendering differences rather than build errors.

The second conflict is with react-native-image-crop-picker, and the fix is more invasive. You have to edit the library's own android/build.gradle, replacing the ucrop dependency line with the pictureselector one at the pinned version 2.7.3-rc08. Then you edit the library's PickerModule.java, changing the uCrop.start call to the form that takes a request code. The README recommends doing this with patch-package, and gives the command to apply the patch.

The patch-package recommendation is the right one, because it makes the modification survive an upgrade of the other library instead of silently disappearing. The deeper point is that two crop-picker libraries cannot both own the crop screen, and the fix here is to swap one implementation for the other inside the other library, which is a kind of surgery that a version bump can undo.

Results, callbacks and the state of the project

The return contract differs by calling style, and that is worth knowing before you write the handler.

Called in callback form, the first argument is the error object and the second is the array of photos. The error object is not null when the user cancels taking a photo, and its message field carries the cancellation message. Called in Promise form, the call resolves directly with the array of images, and a cancelled selection is handled in the catch block instead.

The project state is the last thing to check. The published releases are v0.5.3 on 2021-10-18 and v0.5.1 on 2021-10-18, and the package metadata in the repository reads 0.5.3, so the npm version matches the newest tag. The last push to the repository was on 2026-08-18 and the repository is not archived, so work continues behind the published version.

Two details in the package metadata are worth noting for anyone setting up a release process of their own. The scripts include a test command that echoes an error and exits with a failure, which is the default placeholder rather than a real test suite, and the release process is driven by release-it with the conventional changelog plugin, which writes CHANGELOG.md and creates a v-prefixed tag. The repository does contain a CHANGELOG.md at the top level, along with the licence, the podspec, the android and ios source directories, the example application and the src folder that holds the JavaScript side.

Editorial conclusion

react-native-syan-image-picker fits a React Native team that needs multi selection with cropping and compression and does not want to write the native bridge for both platforms, and that is prepared to maintain the platform configuration it documents. It is the wrong choice for a new project on a current React Native release, since the installation instructions still centre on react-native link and a manual linking path for versions below 0.60, and it is the wrong choice if you need a maintained upstream, because the last published release is from 2021 even though the repository is still being pushed to. Before adopting it, check the linking story against your React Native version, read the Android permission and minSdkVersion requirements, and confirm the cropping and compression options behave the way you need on both platforms.

Frequently asked questions

How do I install react-native-syan-image-picker?

Run npm install react-native-syan-image-picker --save or yarn add react-native-syan-image-picker, then link the native module with react-native link react-native-syan-image-picker. The README also documents a manual linking procedure for React Native versions below 0.60.

Which native pickers does react-native-syan-image-picker use?

PictureSelector by LuckSiege on Android and TZImagePickerController by banchichen on iOS. The module is a wrapper over those two native frameworks rather than its own picker implementation.

Why does cropping not work in react-native-syan-image-picker?

The isCrop option only takes effect when imageCount is 1. The crop size is set by CropW and CropH, which default to 60 percent of the screen width, and showCropCircle switches on a circular crop area.

What Android setup does react-native-syan-image-picker need?

The manifest needs the READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE and CAMERA permissions, minSdkVersion has to be set to 19 in app/build.gradle for PictureSelector, and the storage permission has to be requested at runtime before taking a photo.

How do I get base64 images from react-native-syan-image-picker?

Set the enableBase64 option, which defaults to false. The README also warns that some image properties cannot be obtained when compression is switched off, and that the quality option has no effect on Android, where a fixed compression is used.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. syanbo/react-native-syan-image-picker on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/syanbo-react-native-syan-image-picker.svg)](https://hysenlabs.com/projects/syanbo-react-native-syan-image-picker)

Was this useful?