ShareProvider and shareIntent hook disabled prop not behaving as expected :/
Closed this issue · 6 comments
Describe the bug
Now trying to use expo go, and for some reason setting the disabled flag to true in both the hook and provider give me this error when I am importing into the _layout.tsx file.
ERROR Error: Cannot find native module 'ExpoShareIntentModule', js engine: hermes
at ContextNavigator (http://10.1.10.101:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:276602:24)
at ExpoRoot (http://10.1.10.101:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:276558:28)
at App
at ErrorToastContainer (http://10.1.10.101:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:378383:24)
at ErrorOverlay
at withDevTools(ErrorOverlay) (http://10.1.10.101:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:377845:27)
at RCTView
at View (http://10.1.10.101:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:40974:43)
at RCTView
at View (http://10.1.10.101:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:40974:43)
at AppContainer (http://10.1.10.101:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:40785:36)
at main(RootComponent) (http://10.1.10.101:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:124770:28)
The only way I am able to have the ShareIntent module resolve correctly in my project for expo-go is calling the hook like so...
import "../utils/firebase.utils";
import { useFonts } from "expo-font";
import { SplashScreen, Stack } from "expo-router";
import { useEffect } from "react";
import { Platform } from "react-native";
import AppContainer from "../components/AppContainer/AppContainer";
import React from "react";
import { RegisterContextProviders } from "../components/RegisterContextProviders/RegisterContextProviders";
import { useTrackDeviceLocation } from "../hooks/useTrackDeviceLocation";
import { FontFamily } from "styles";
import { useAuthentication } from "@hooks/useAuthentication";
import { HomeLoadingScreen } from "@components/Loading/HomeLoadingScreen";
import Constants from "expo-constants";
export { ErrorBoundary } from "expo-router";
export const unstable_settings = {
initialRouteName: "(tabs)",
};
if (Platform.OS !== "web") SplashScreen.preventAutoHideAsync();
// Separate component to handle share intent
const ShareIntentComponent = () => {
const { useShareIntent } = require("expo-share-intent");
const { hasShareIntent, shareIntent, resetShareIntent } = useShareIntent();
useEffect(() => {
if (hasShareIntent) {
console.log("Received share intent:", shareIntent);
resetShareIntent();
}
}, [hasShareIntent, shareIntent, resetShareIntent]);
return null; // This component does not render anything
};
const RootLayout = () => {
const [loaded, error] = useFonts({
[FontFamily["DM Sans-Light"]]: require("../assets/fonts/DMSans/DMSans-Light.ttf"),
[FontFamily["DM Sans-Regular"]]: require("../assets/fonts/DMSans/DMSans-Regular.ttf"),
[FontFamily["DM Sans-Medium"]]: require("../assets/fonts/DMSans/DMSans-Medium.ttf"),
[FontFamily["DM Sans-Bold"]]: require("../assets/fonts/DMSans/DMSans-Bold.ttf"),
[FontFamily["DM Sans-Italic"]]: require("../assets/fonts/DMSans/DMSans-Italic.ttf"),
});
useTrackDeviceLocation();
useEffect(() => {
if (error) console.warn(error);
}, [error]);
useEffect(() => {
if (loaded) {
SplashScreen.hideAsync();
}
}, [loaded]);
if (!loaded) {
return null;
}
return <RootLayoutNav />;
};
export default function RootLayoutWithContext() {
return (
<RegisterContextProviders>
{Constants.appOwnership !== "expo" && <ShareIntentComponent />}
<RootLayout />
</RegisterContextProviders>
);
}
function RootLayoutNav() {
useAuthentication();
return (
<AppContainer>
<HomeLoadingScreen />
<Stack
screenOptions={{
headerShown: false,
navigationBarHidden: true,
}}
initialRouteName="index"
>
<Stack.Screen name="index" />
</Stack>
</AppContainer>
);
}
###However in trying this, I am getting the error stated above, and never actually reaching the console.log() statements in my RootLayoutWithContext function
import React, { useEffect } from "react";
import { Platform, Text } from "react-native";
import { useFonts } from "expo-font";
import { SplashScreen, Stack, router } from "expo-router";
import Constants from "expo-constants";
import AppContainer from "../components/AppContainer/AppContainer";
import { RegisterContextProviders } from "../components/RegisterContextProviders/RegisterContextProviders";
import { useTrackDeviceLocation } from "../hooks/useTrackDeviceLocation";
import { FontFamily } from "styles";
import { useAuthentication } from "@hooks/useAuthentication";
import { HomeLoadingScreen } from "@components/Loading/HomeLoadingScreen";
import { ShareIntentProvider } from "expo-share-intent";
export { ErrorBoundary } from "expo-router";
export const unstable_settings = {
initialRouteName: "(tabs)",
};
if (Platform.OS !== "web") SplashScreen.preventAutoHideAsync();
const RootLayout = () => {
const [loaded, error] = useFonts({
[FontFamily["DM Sans-Light"]]: require("../assets/fonts/DMSans/DMSans-Light.ttf"),
[FontFamily["DM Sans-Regular"]]: require("../assets/fonts/DMSans/DMSans-Regular.ttf"),
[FontFamily["DM Sans-Medium"]]: require("../assets/fonts/DMSans/DMSans-Medium.ttf"),
[FontFamily["DM Sans-Bold"]]: require("../assets/fonts/DMSans/DMSans-Bold.ttf"),
[FontFamily["DM Sans-Italic"]]: require("../assets/fonts/DMSans/DMSans-Italic.ttf"),
});
useTrackDeviceLocation();
useEffect(() => {
if (error) console.warn(error);
}, [error]);
useEffect(() => {
if (loaded) {
SplashScreen.hideAsync();
}
}, [loaded]);
if (!loaded) {
return <Text>Loading Fonts...</Text>; // Provides feedback during loading
}
return <RootLayoutNav />;
};
export default function RootLayoutWithContext() {
// Detect if running in an environment without support for native modules
const isExpoGo = Constants.appOwnership === "expo";
console.log("Is Expo Go:", isExpoGo);
console.log("Provider Disabled:", isExpoGo);
return (
<ShareIntentProvider
options={{
disabled: true, // Disable in unsupported environments like Expo Go
debug: true,
resetOnBackground: true,
onResetShareIntent: () => {
router.replace({
pathname: "/",
});
},
}}
>
<RegisterContextProviders>
<RootLayout />
</RegisterContextProviders>
</ShareIntentProvider>
);
}
function RootLayoutNav() {
useAuthentication();
return (
<AppContainer>
<HomeLoadingScreen />
<Stack
screenOptions={{
headerShown: false,
navigationBarHidden: true,
}}
initialRouteName="index"
>
<Stack.Screen name="index" />
</Stack>
</AppContainer>
);
}
Environment
System:
OS: macOS 14.3
CPU: (10) arm64 Apple M1 Max
Memory: 2.40 GB / 64.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 18.17.1
path: ~/.nvm/versions/node/v18.17.1/bin/node
Yarn:
version: 1.22.19
path: ~/.nvm/versions/node/v16.17.0/bin/yarn
npm:
version: 9.6.7
path: ~/.nvm/versions/node/v18.17.1/bin/npm
Watchman: Not Found
Managers:
CocoaPods:
version: 1.15.2
path: /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 23.4
- iOS 17.4
- macOS 14.4
- tvOS 17.4
- visionOS 1.1
- watchOS 10.4
Android SDK: Not Found
IDEs:
Android Studio: 2022.2 AI-222.4459.24.2221.10121639
Xcode:
version: 15.3/15E204a
path: /usr/bin/xcodebuild
Languages:
Java:
version: 18.0.1
path: /usr/bin/javac
Ruby:
version: 2.6.10
path: /usr/bin/ruby
npmPackages:
"@react-native-community/cli": Not Found
react:
installed: 18.2.0
wanted: 18.2.0
react-native:
installed: 0.73.6
wanted: 0.73.6
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: false
iOS:
hermesEnabled: true
newArchEnabled: false
- expo version (ex: 49) : 50
- using firebase : yes, js sdk
- using static build : not sure
- routing : expo-router
- package version (ex: 1.2.0) : 1.5.2
- platform target : iOS
- device : both
🤔
When you use the provider with disabled option, do you call the hook useShareIntentContext ? i didn't see it in your example (Should not use useShareIntent with provider). Or it just crash with the provider only ?
@achorein I do not call the useShareIntentContext when using the provider you created, before I even get that far the project will fail. The console log statements in my RootLayoutWithContext() inside the _layout.tsx file are not even getting triggered in expo go because it fails to resolve the import, I believe. Not sure how to get around that, even after following your specifications.
Right now my solution is to instead use the useShareIntent hook, which is imported in the require statement inside of a conditionally rendered component inside of my _layout.tsx file.
I know I sent large code blocks that are difficult to parse, so lmk if you need me to consolidate or expand more. Thank you!
@achorein would like to bump you on this! I know you have a life haha
I'm just curious why I can't use the package in the project without it failing unless if I do this, do you have any direction? :)
necessary structure of the component in order to make it compile
import { encodeWaypointForQueryString } from "@utils/map.utils";
import { trpc } from "@utils/trpc.utils";
import { router } from "expo-router";
import { useEffect, useState } from "react";
function parseShareIntentText(text: string) {
// Splitting the text into place name and URL
const splitIndex = text.indexOf("https://");
if (splitIndex === -1) {
console.error("No URL found in the text.");
return null;
}
const placeName = text.substring(0, splitIndex).trim();
const url = text.substring(splitIndex).trim();
const urlObj = new URL(url);
const llParam = urlObj.searchParams.get("ll");
if (!llParam) {
console.error("Latitude and longitude not found in the URL.");
return null;
}
const [lat, lng] = llParam.split(",").map(Number);
return {
placeName,
latitude: lat,
longitude: lng
};
}
// Separate component to handle share intent
export const ShareIntent = () => {
const { useShareIntent } = require("expo-share-intent");
const { hasShareIntent, shareIntent, resetShareIntent } = useShareIntent();
const [parsedData, setParsedData] = useState<{ placeName: string; latitude: number; longitude: number } | null>(null);
const { data } = trpc.routing.getPlaceInfoFromLatLng.useQuery(
{
lat: parsedData?.latitude ?? 0,
lng: parsedData?.longitude ?? 0,
radius: 100,
keyword: parsedData?.placeName
},
{ enabled: !!parsedData }
);
useEffect(() => {
if (hasShareIntent) {
const parsedIntentData = parseShareIntentText(shareIntent.text);
if (parsedIntentData) {
setParsedData(parsedIntentData);
}
resetShareIntent();
}
}, [hasShareIntent, shareIntent, resetShareIntent]);
useEffect(() => {
if (!data) return;
const placeId = data[0].place_id ?? null;
if (placeId) {
const encodedWaypoint = encodeWaypointForQueryString({ id: placeId, t: "p" });
router.navigate(`/launchpad/map/place/${encodedWaypoint}`);
}
}, [data]);
return null;
};
importing it into my layout file
{Constants.appOwnership !== "expo" && Platform.OS !== "web" && <ShareIntent />}
Got ya!