Skip to content
This repository has been archived by the owner on Mar 5, 2024. It is now read-only.

getting a "this screen doesn't exist" with expo router #14

Closed
spencerc99 opened this issue Sep 20, 2023 · 12 comments
Closed

getting a "this screen doesn't exist" with expo router #14

spencerc99 opened this issue Sep 20, 2023 · 12 comments
Labels
documentation Improvements or additions to documentation example

Comments

@spencerc99
Copy link

hi there! thanks so much for making this demo

I got as far as getting it onto my iOS device using your useShareIntent hook, and my app successfully shows up in the share sheet! But when I send something to the app, I'm getting a "this screen doesn't exist." I wonder if it's due to using Expo Router? Would love any ideas!

361782FA-0020-4832-A462-B7184683ADC2_1_102_o

@achorein
Copy link
Owner

👋
Indeed my demo doesn't have a expo-router or react-navigation example.

To use expo-router you need to handle Unmatched Routes . It's the only screen where useShareIntent hook will work (allowing to get custom pathname).

Here an example for app/[...unmatched].js file :

export default function Unmatched() {
  const pathname = usePathname();
  const router = useRouter();

  const { shareIntent, resetShareIntent } = useShareIntent();

  return (
    <View style={styles.container}>
      <Text style={styles.gap}>Screen could not be found : {pathname}</Text>
      <Text style={styles.gap}>{JSON.stringify(shareIntent)}</Text>
      <Text
        onPress={() => {
          if (router.canGoBack()) {
            router.back();
          } else {
            router.replace("/");
          }
        }}
      >
        Go back.
      </Text>
    </View>
  );
}

You can also get the shareintent data from here and navigate to a specific screen with parameters to split the code.
To detect your are coming from a share intent you can test the pathname like that :

  if (pathname?.includes(`dataurl=${Constants.expoConfig.scheme}sharekey`) && shareIntent) {
     router.replace({ pathname: 'shareintent', params: { shareIntent } })
  }

let me know if you managed to get it to work, I will update the documentation afterwards

@spencerc99
Copy link
Author

spencerc99 commented Sep 20, 2023

ahhh awesome thank you for the detailed explanation I'm very new to expo and expo router, so this is perfect info. Will try this out and let you know how it goes!

Btw did you figure out a way to test this in development? I notice that the default expo dev flow uses Expo Go in the simulator and so there's no share intent for the app there. What's the recommended way for testing this or do I have to actually build it and transfer it to my device each time?

@achorein
Copy link
Owner

achorein commented Sep 20, 2023

We are using native code to make share intent works, so we can't use Expo Go and have to use a custom dev client, that's why the demo use expo prebuild --no-install command and then expo run:ios, instead of a simple expo start --ios.
More information here

That way you can test your share intent into simulator, but that does not exempt you to test a complete build on device at the end of your development process to make sure all works as excepted :)

@achorein
Copy link
Owner

working example with expo router is now available on branch expo49-expo-router, enjoy !

@achorein achorein added documentation Improvements or additions to documentation enhancement New feature or request example and removed enhancement New feature or request labels Sep 20, 2023
@spencerc99
Copy link
Author

spencerc99 commented Sep 20, 2023

thank you for the help! Unfortunately, I still seem to be running into issues. I followed your code in the attached branch and was able to get it running in the emulator and successfully show up in the share intent screen. However, when I share to the app, I don't seem to be getting any share intent data when using the hook strangely.

Screen.Recording.2023-09-20.at.3.10.03.PM.mov

In my logs, I see that the share intent is being set, but it's not causing my component to re-render or that useEffect you use to redirect to trigger.

image
this is probably an error on my part, but wondering if you have any ideas?

code below:

// [...unmatched.tsx]
export default function NotFoundScreen() {
  const pathname = usePathname();
  const router = useRouter();
  const { shareIntent, resetShareIntent } = useShareIntent();
  console.log("pathname", pathname, shareIntent);
  useEffect(() => {
    console.log("checking share intent", pathname, shareIntent);
    if (
      pathname?.includes(`dataurl=${Constants.expoConfig?.scheme}sharekey`) &&
      shareIntent
    ) {
      console.log("redirecting!");
      router.replace({ pathname: "/(tabs)/home", params: { shareIntent } });
      resetShareIntent();
    }
  }, [shareIntent]);

  return (
    <>
      <Stack.Screen options={{ title: "Oops!" }} />
      <View style={styles.container}>
        <Text style={styles.title}>This screen doesn't exist.</Text>

        <Text
          style={styles.linkText}
          onPress={() => {
            if (router.canGoBack()) {
              router.back();
            } else {
              router.replace({ pathname: "/(tabs)/home" });
            }
          }}
        >
          Go back.
        </Text>
      </View>
    </>
  );
}

and my useShareIntent hook is the same except i added a "[rerendering] useShareIntentHook" log at the bottom before return

@spencerc99
Copy link
Author

thank you for the help! Unfortunately, I still seem to be running into issues. I followed your code in the attached branch and was able to get it running in the emulator and successfully show up in the share intent screen. However, when I share to the app, I don't seem to be getting any share intent data when using the hook strangely.

Screen.Recording.2023-09-20.at.3.10.03.PM.mov
In my logs, I see that the share intent is being set, but it's not causing my component to re-render or that useEffect you use to redirect to trigger.

image this is probably an error on my part, but wondering if you have any ideas?

code below:

// [...unmatched.tsx]
export default function NotFoundScreen() {
  const pathname = usePathname();
  const router = useRouter();
  const { shareIntent, resetShareIntent } = useShareIntent();
  console.log("pathname", pathname, shareIntent);
  useEffect(() => {
    console.log("checking share intent", pathname, shareIntent);
    if (
      pathname?.includes(`dataurl=${Constants.expoConfig?.scheme}sharekey`) &&
      shareIntent
    ) {
      console.log("redirecting!");
      router.replace({ pathname: "/(tabs)/home", params: { shareIntent } });
      resetShareIntent();
    }
  }, [shareIntent]);

  return (
    <>
      <Stack.Screen options={{ title: "Oops!" }} />
      <View style={styles.container}>
        <Text style={styles.title}>This screen doesn't exist.</Text>

        <Text
          style={styles.linkText}
          onPress={() => {
            if (router.canGoBack()) {
              router.back();
            } else {
              router.replace({ pathname: "/(tabs)/home" });
            }
          }}
        >
          Go back.
        </Text>
      </View>
    </>
  );
}

and my useShareIntent hook is the same except i added a "[rerendering] useShareIntentHook" log at the bottom before return

well i tried again later and now it's magically working 😅 thanks for the help!

@spencerc99
Copy link
Author

btw is there a better way to remove the auto-generated

 "build": {
          "experimental": {
            "ios": {
              "appExtensions": [
                {
                  "targetName": "ShareExtension",
                  "bundleIdentifier": "supply.basket.share-extension",
                  "entitlements": {
                    "com.apple.security.application-groups": [
                      "group.supply.basket"
                    ]
                  }
                }
              ]
            }
          }
        }

that gets adds to "eas" in app.json. I seem to have to do it manually each time after build. Related to #1 (let me know if you want me to open a new issue)

@spencerc99
Copy link
Author

thank you for the help! Unfortunately, I still seem to be running into issues. I followed your code in the attached branch and was able to get it running in the emulator and successfully show up in the share intent screen. However, when I share to the app, I don't seem to be getting any share intent data when using the hook strangely.
Screen.Recording.2023-09-20.at.3.10.03.PM.mov
In my logs, I see that the share intent is being set, but it's not causing my component to re-render or that useEffect you use to redirect to trigger.
image this is probably an error on my part, but wondering if you have any ideas?
code below:

// [...unmatched.tsx]
export default function NotFoundScreen() {
  const pathname = usePathname();
  const router = useRouter();
  const { shareIntent, resetShareIntent } = useShareIntent();
  console.log("pathname", pathname, shareIntent);
  useEffect(() => {
    console.log("checking share intent", pathname, shareIntent);
    if (
      pathname?.includes(`dataurl=${Constants.expoConfig?.scheme}sharekey`) &&
      shareIntent
    ) {
      console.log("redirecting!");
      router.replace({ pathname: "/(tabs)/home", params: { shareIntent } });
      resetShareIntent();
    }
  }, [shareIntent]);

  return (
    <>
      <Stack.Screen options={{ title: "Oops!" }} />
      <View style={styles.container}>
        <Text style={styles.title}>This screen doesn't exist.</Text>

        <Text
          style={styles.linkText}
          onPress={() => {
            if (router.canGoBack()) {
              router.back();
            } else {
              router.replace({ pathname: "/(tabs)/home" });
            }
          }}
        >
          Go back.
        </Text>
      </View>
    </>
  );
}

and my useShareIntent hook is the same except i added a "[rerendering] useShareIntentHook" log at the bottom before return

well i tried again later and now it's magically working 😅 thanks for the help!

hmm I seem to experience that this works sporadically between restarts (and differs in behavior between using a link and an image). Any ideas on why that would be the case?

@achorein
Copy link
Owner

achorein commented Sep 21, 2023

that gets adds to "eas" in app.json. I seem to have to do it manually each time after build. Related to #1 (let me know if you want me to open a new issue)

as mention you just have to add your projectId in app.json

hmm I seem to experience that this works sporadically between restarts (and differs in behavior between using a link and an image). Any ideas on why that would be the case?

ok I'm going to test it in more depth on my side

@achorein
Copy link
Owner

achorein commented Sep 21, 2023

@spencerc99 i finally found a fix for this fee330a.

So

  • we can't use "unmatched" screen, because deep linking url not available anymore here
  • must use Layout to handle app loading elements
  • I also update useShareIntent hook to auto refresh data when application became active

@spencerc99
Copy link
Author

@achorein amazing!! i will check this out tonight.

I also realized there's an interface distinction between the share intent triggering the opening of the app with the data and apps opening a pop-up screen to handle the share in-context. Do you know if that's supported with the react-native-share-intent library you are using / if there's a different solution for that?

@achorein
Copy link
Owner

as mentioned in #15 this project does not support custom view for ios, all the share intent must be handle into the app.

I close the issue, I think we have covered the subject of expo-router. feel free to re-open if problem persist.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
documentation Improvements or additions to documentation example
Projects
None yet
Development

No branches or pull requests

2 participants