react-native: Assets uri's that begin with ph:// cause error
Description
When giving the Image
component a uri
beginning with ph://
like so:
<Image source={{ uri: "ph://*" }} />
the image fails to render:
In my scenario, I used expo-media-library
to retrieve the uri’s. I built my app with the old architecture, and this error did not persist.
Version
0.71.1
Output of npx react-native info
System: OS: macOS 13.2 CPU: (8) arm64 Apple M1 Memory: 75.11 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 18.13.0 - ~/.nvm/versions/node/v18.13.0/bin/node Yarn: 1.22.19 - ~/.nvm/versions/node/v18.13.0/bin/yarn npm: 8.19.3 - ~/.nvm/versions/node/v18.13.0/bin/npm Watchman: 2023.01.30.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.11.3 - /opt/homebrew/bin/pod SDKs: iOS SDK: Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1 Android SDK: Not Found IDEs: Android Studio: Not Found Xcode: 14.2/14C18 - /usr/bin/xcodebuild Languages: Java: Not Found npmPackages: @react-native-community/cli: Not Found react: 18.2.0 => 18.2.0 react-native: 0.71.1 => 0.71.1 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found
Steps to reproduce
- get a uri starting with
ph://
by any means - render an image with that uri
Snack, code example, screenshot, or link to a repository
Not sure how to switch a snack into the new architecture, but this code in the new architecture will fail:
https://snack.expo.dev/gv6bMd2MY?platform=ios
UPDATE: Providing a simpler example to convey that this is a react native issue and not due to any dependency. The following code fails on the new archatecure with the error above:
import React from 'react';
import { Image } from 'react-native';
const App = () => {
return <Image source={{ uri: 'ph://B84E8479-475C-4727-A4A4-B77AA9980897' }} style={{ width: 100, height: 100 }} />;
};
export default App;
but it runs exactly as expected in the old one. It looks like the new architecture can not handle iOS’s ph:// routes.
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 19 (9 by maintainers)
@norbusonam @mrousavy @tsapeta I spin up an app with 0.71.1, and the Old Architecture fails in the same way as the new one.
Repro:
I retrieved the ID by:
NSPhotoLibraryUsageDescription
in the capabilities in XcodePhotos
framework in the Frameworks, Libraries and Embedded Contents in the General tab of the project in XcodeThen, replace the App.tsx content with the following:
For my simulator,
106E99A1-4F6A-45A2-B320-B0AD4A8E8473
is a valid id for an asset in the camera roll.When I run the app in the Old Architecture, I get the same error message:
Could it be that, in the Old Architecture, the libraries were able to self register their image handler in the list of handlers? So, what I think was happening:
yarn add react-native-cameraroll
#and example of library that can handleph://
url schemasNSPhotoLibraryUsageDescription
And it looked like React Native is able to manage the
ph://
directly, but it was actually a library handling that?That fits with my understanding and as a difference between New/Old Arch. In fact, libraries couldn’t, before 0.74, register themselves as URL Handlers/Image Loaders in the New Architecture.
up, we don’t want for this issue to be reaped. We will work on this next half.
Closing this as it is an intended React Native behaviour.
The Old Architecture is relying on some library to pick up the
ph://
protocol. Libraries on the Old Architecture can register automatically to respond to custom URL protocols, that’s why it looked like React Native was able to load images using theph://
protocol.In the New Architecture, before 0.74, libraries could not register themselves as URL handler, hence, this issue has been opened. In 0.74, thanks to this PR, libraries can now register themselves as URL handler, filling the gap between the Old and the New architecture.
Sharing some findings and a solution that worked for me:
Findings
According to this issue React Native no longer support’s
ph://
routes after@react-native-camera-roll/camera-roll
was separated, and installing@react-native-camera-roll/camera-roll
should integrate the proper handler. However, according to this issue the new architecture hard codesRCTURLRequestHandler
, which means simply installing@react-native-camera-roll/camera-roll
won’t be enough to solve the problem.Solution
Ultimetly, I was able to work around this by:
@react-native-camera-roll/camera-roll
getModuleInstanceFromClass
in yourAppDelegate.mm
to use@react-native-camera-roll/camera-roll
’sRNCAssetsLibraryRequestHandler
handler:Extra Info
After these finding’s I realized the reason
ph://
routes were working on the old architecture was likely because expo provides aEXImageLoader
. And since the new architecture hardcodesRCTURLRequestHandler
, it did now work there.Hi @norbusonam, thank you for opening the issue and to explore it further. We are aware of this limitation for the new Architecture, unfortunately. I see you found the PR trying to fix that, but we are not convinced by that fix yet.
Your override is a good workaround for the time being, while we find a better solution.
Just mean that the URI starts with
ph://
. These URI’s route to PHAssets in iOS (basically just photo library assets).That issue with permissions was just an
expo-image
thing.The problem here is that React Native’s core
Image
component errors when it tries to render any image with aph://
on the new architecture. I confirmed this was a regression from the old architecture.EDIT: To clarify, the user does need to grant either limited or full access to photo library to render a photo library image, but that is not the main issue here
please save me!!!
As this is related to
expo-media-library
(which lives here https://github.com/expo/expo/tree/main/packages/expo-media-library) and their support for New Architecture, you should open this issue against Expo’s repo.