kanzitelli/expo-starter

Deep linking support

ssk-mps opened this issue ยท 6 comments

Thank you for creating this fantastic resource! ๐Ÿ™

In my codebase, I have something like this for deep linking

import { NavigationContainer } from '@react-navigation/native';

function App() {
  const linking = {
    prefixes: ['https://mychat.com', 'mychat://'],
    config: {
      screens: {
        Home: 'feed/:sort',
      },
    },
  };

  return (
    <NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
      {/* content */}
    </NavigationContainer>
  );
}

With the latest version of expo-started, I noticed that it is using a rn-navio library. But there is no way to provide custom linking prop. This is very crucial for production apps.

https://reactnavigation.org/docs/navigation-container/#linking
https://docs.expo.dev/guides/deep-linking/

Hi @ssk-mps! Thank you!

And yes, you can achieve it with rn-navio as it's fully built on React Navigation. Once you built your layout with const navio = Navio.build(...), you can generate <navio.Root /> component which takes two arguments initialRouteName and navigationContainerProps. The latter will be passed directly to NavigationContainer. In your case, it's going to be something like <navio.Root navigationContainerProps={{linking: yourLinkings}} /> (as here, AppRoot == navio.Root).

That's awesome! Thanks for the pointer. It would be great to document this in the rn-navio readme file.

What is the best way to get the RootStackParamList that is generated by rn-navio? Here is the code that I have:

import { LinkingOptions } from '@react-navigation/native';
import * as Linking from 'expo-linking';

import { RootStackParamList } from '../types';

const linking: LinkingOptions<RootStackParamList> = {
  prefixes: [Linking.createURL('/')],
  config: { ... }
}

and I've explicitly defined the type of RootStackParamList as follows:

export type RootStackParamList = {
  Root: NavigatorScreenParams<RootTabParamList> | undefined;
  Modal: undefined;
  NotFound: undefined;
};

hey @ssk-mps! Glad it helped! And definitely, I am collecting some feedback and feature requests that will be implemented in the next releases.

Could you elaborate more on that and give broader example with use cases? That would be helpful as I don't fully get it.

Hi @kanzitelli The use-case is pretty much TypeScript type safety. When I declare const linking = {...}, then TS doesn't know what this object should be. But when I declare const linking: LinkingOptions<RootStackParamList> = { ... } then TS can catch the problems in the linking. This is why LinkingOptions type is exposed by @react-navigation/native. I hope it helps

@ssk-mps ah okay, got it! so currently rn-navio doesn't provide a type that describes the structure of the app, RootStackParamList in your case. maybe I'll come up with something in the future. I will add it into README as well, but now you will need to define it yourself as you do. the structure that navio builds might look like this:

const navio = Navio.build({
  screens: {
    Main,
    Settings,
    Example,
    Playground,
  },
  stacks: {
    MainStack: ['Main', 'Example'],
    ExampleModalStack: ['Example'],
  },
  tabs: {
    MainTab: {
      stack: 'MainStack',
    },
    PlaygroundTab: {
      stack: ['Playground'],
    },
    SettingsTab: {
      stack: ['Settings'],
    },
  },
  modals: {
    ExampleModal: 'ExampleModalStack',
  },
  root: 'Tabs', // 'Tabs' by default; takes also any stack name as a value
});

export type RootStackParamList = {
  // tabs
  Tabs: {
    MainTab: {
       Main: <props>,
       Example: <props>,
    },
    PlaygroundTab: {
      Playground: <props>,
    },
    SettingsTab: {
       Settings: <props>,
    },
  },
  
  // stacks, as you can .pushStack() as well
  ExampleStack: { 
    Example: <props>
  },
  
  // modals
  ExampleModal: {
    Example: <props>
  }
}

Hope it helps! And let me know how it works in your case :)

That works for me! Thanks @kanzitelli Please feel free to close this issue.