Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example to use it with expo go #23

Closed
linonetwo opened this issue Mar 15, 2024 · 8 comments
Closed

Example to use it with expo go #23

linonetwo opened this issue Mar 15, 2024 · 8 comments

Comments

@linonetwo
Copy link

Sometimes we just want to use expo go to debut other parts of app, here is how to do it

/* eslint-disable @typescript-eslint/strict-boolean-expressions */
import type { useShareIntent as IUseShareIntent } from 'expo-share-intent';
import { useEffect } from 'react';
import { useRegisterProxy } from 'react-native-postmessage-cat';
import { nativeService } from '.';
import { NativeServiceIPCDescriptor } from './descriptor';

export function useNativeService() {
  const [webViewReference, onMessageReference] = useRegisterProxy(nativeService, NativeServiceIPCDescriptor);
  return [webViewReference, onMessageReference] as const;
}

export function useRequestNativePermissions() {
  useEffect(() => {
    void (async () => {
      await nativeService.requestCameraPermission();
      await nativeService.requestMicrophonePermission();
    })();
  }, []);
}

export function useRegisterReceivingShareIntent() {
  /** If you get error on development:
   * ```
   *  Error: Cannot find native module 'ExpoShareIntentModule', js engine: hermes
   * Invariant Violation: "main" has not been registered. This can happen if:
   * Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
   * A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called., js engine: hermes
   * ```
   *
   * Comment out this import will work.
   *
   * Also comment out all code inside `useRegisterReceivingShareIntent`.
   */
  if (process.env.NODE_ENV === 'development') {
    return;
  }
  const { useShareIntent } = require('expo-share-intent') as { useShareIntent: typeof IUseShareIntent };
  /* eslint-disable react-hooks/rules-of-hooks */
  const { hasShareIntent, shareIntent, resetShareIntent, error } = useShareIntent({
    debug: true,
  });

  useEffect(() => {
    if (error !== undefined) {
      console.log(
        `Failed to get ShareIntent, This is normal if you are using Expo Go for dev. To debug sharing feature, create a dev build "pnpm start:devClient" instead. ${error}`,
      );
    }
    void (async () => {
      try {
        if (hasShareIntent) {
          await nativeService.receivingShareIntent(shareIntent);
          resetShareIntent();
        }
      } catch (error) {
        console.log(
          `Failed to registerReceivingShareIntent, This is normal if you are using Expo Go for dev. To debug sharing feature, create a dev build "pnpm start:devClient" instead. ${
            (error as Error).message
          }`,
        );
      }
    })();
  }, [hasShareIntent, shareIntent, resetShareIntent, error]);
}

and start it with

"android": "cross-env NODE_ENV=development expo start --go --android",

It was easier when this lib also export non-hook api, but I find it is possible to workaround it today, so share with anyone with same problem.

linonetwo added a commit to tiddly-gittly/TidGi-Mobile that referenced this issue Mar 15, 2024
@achorein
Copy link
Owner

achorein commented Mar 15, 2024

wow !
thanks for sharing your example, sounds a bit complex but it's a good start :)

wondering if i can add something like that in a futur version :

useShareIntent({
    disabled: true,
});

@linonetwo
Copy link
Author

linonetwo commented Mar 15, 2024

Notice that my previous code that use expo-share-intent was:

import { ShareIntent } from 'expo-share-intent';

/// ...

      if (process.env.NODE_ENV === 'development') {
        return;
      }
      ReceiveSharingIntent.getReceivedFiles(
        async (
          files: ISharedFile[],
        ) => {
// ...

If I early return, just before actually calling the imperactive api, it was safe.

But in this version it still throw error when import the hook

import { useShareIntent } from 'expo-share-intent';

// ...
  if (process.env.NODE_ENV === 'development') {
    return;
  }
  /* eslint-disable react-hooks/rules-of-hooks */
  const { hasShareIntent, shareIntent, resetShareIntent, error } = useShareIntent({
    debug: true,
  });

Still throw the error Error: Cannot find native module 'ExpoShareIntentModule', js engine: hermes! So my workaround above use require inline.

@linonetwo
Copy link
Author

Anyway this workaround does work, just for people googled here, closing this issue.

I haven't get sharing work yet, because expo's dev client is not working, and they don't want to fix it expo/expo#27536

@achorein
Copy link
Owner

🤔 By the way, ReceiveSharingIntent.getReceivedFiles should not be used with this package, make sure you removed expo-config-plugin-ios-share-extension and react-native-receive-sharing-intent.

@linonetwo
Copy link
Author

Thanks, I know that, I was just post old code to illustrate that old package can import and then conditionally block execution. But the new package is different.

@achorein achorein mentioned this issue Mar 18, 2024
9 tasks
@achorein
Copy link
Owner

You can now simply disabled share intent to run it into expo go (v1.2.0 and v0.4.0)

For example :

const { shareIntent } = useShareIntent({ disabled: process.env.NODE_ENV === 'development'})
<ShareIntentProvider options={{ disabled: process.env.NODE_ENV === 'development'}}>
  <App />
</ShareIntentProvider>

@linonetwo
Copy link
Author

Many thanks, this is convenient.

@Episodex
Copy link

Hi, I'm trying to use this new disabled option, but I can't get it to work. I downloaded the repo and modified expo-router example by just adding disabled: true in _layout.tsx:

export default function Layout() {
  const router = useRouter();

  return (
    <ShareIntentProvider
      options={{
        disabled: true,
        debug: true,
        resetOnBackground: true,
        onResetShareIntent: () =>
          // used when app going in background and when the reset button is pressed
          router.replace({
            pathname: "/",
          }),
      }}
    >
      <Slot />
    </ShareIntentProvider>
  );
}

When running the code using expo start I get:

 ERROR  TypeError: Cannot read property 'useState' of null

This error is located at:
    in ShareIntentProvider (created by Layout)
    in Layout
    in Unknown (created by Route())
    in Suspense (created by Route())
    in Route (created by Route())
    in Route() (created by ContextNavigator)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by wrapper)
    in wrapper (created by ContextNavigator)
    in EnsureSingleNavigator
    in BaseNavigationContainer
    in ThemeProvider
    in NavigationContainerInner (created by ContextNavigator)
    in ContextNavigator (created by ExpoRoot)
    in ExpoRoot (created by App)
    in App (created by ErrorOverlay)
    in ErrorToastContainer (created by ErrorOverlay)
    in ErrorOverlay (created by withDevTools(ErrorOverlay))
    in withDevTools(ErrorOverlay)
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent), js engine: hermes

Also it complains about the rule of hooks violation.

I tried to use the package in my project with disabled: true but it also doesn't work. That's why I tried with the example.

Is this example correct at the moment? Do I do something wrong?

Btw, thank you very much for this package and updates to it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants