Skip to content

Instantly share code, notes, and snippets.

@satya164
Last active January 10, 2023 21:54
Show Gist options
  • Save satya164/73643343a4a2b439b13704ddd92b199a to your computer and use it in GitHub Desktop.
Save satya164/73643343a4a2b439b13704ddd92b199a to your computer and use it in GitHub Desktop.
React Navigation Static API

React Navigation Static API

React Navigation has a dynamic API which makes it possible to achieve advanced and use cases. But it can result in additional boilerplate and duplication. The goal of this static API is to provide a simpler API for simple use cases.

Basic API

const MyNavigation = createNavigation({
  // Type of the navigator, takes the 'createXNavigator' function from respective package
  type: createStackNavigator,
  // Any props accepted by the navigator
  initialRouteName: 'Home',
  keyboardHandlingEnabled: false,
  // List of screens in the navigator
  screens: {
    Home: {
      // Screens with nested navigators need to specify `type` and `screens` instead of `component`
      type: createBottomTabNavigator,
      screens: {
        Feed: {
          component: FeedScreen,
          options: {
            title: 'Feed',
          },
        },
      },
    },
    Profile: {
      // The component to render for this screen
      component: ProfileScreen,
      // Options for the screen
      options: ({ route, data }) => ({
        title:
          // The additional `data` parameter can be used to configure the screen based on dynamic data
          data.me === route.params.username
            ? 'My Profile'
            : `@${route.params.username}'s Profile`,
      }),
      // ID for navigating to new screens
      getId: ({ route }) => route.params.username,
      // Path for linking integration
      path: 'profile/:username',
    },
    // It's possible to specify a component directly
    Settings: SettingsScreen,
  },
});

The MyNavigation component can be directly used or rendered to pass additional props to the NavigationContainer. It takes the same props as the NavigationContainer component except linking, which is automatically configured based on the path properties in the configuration. In addition, it also accepts a data prop that can be used to for dynamic options.

export default function App() {
  return (
    <MyNavigation
      data={{ me: 'jane' }}
      onStateChange={() => {
        // Do something on navigation
      }}
    />
  );
}

TypeScript

The TypeScript setup is different from how it's done with the regular API. Each screen component needs to specify the type of the route prop:

type Props = {
  route: {
    params: {
      username: string;
    };
  };
};

function ProfileScreen({ route }: Props) {
  // ...
}

The type of Props can be specified with the StaticScreenProps alias in a simpler way:

type Props = StaticScreenProps<{
  username: string;
}>;

The navigation prop isn't passed to the screen component with the static configuration. Users need to use the useNavigation hook instead. To TypeCheck the useNavigation hook, a default type can be specified as follows:

declare global {
  namespace ReactNavigation {
    interface RootParamList extends StaticParamList<typeof Navigation> {}
  }
}

Authentication

Since the navigation is static, it's not possible to conditionally render a screen based on the authentication state. Instead, the condition can be specified with the if property in the config:

type Data = {
  isSignedIn: boolean;
};

const MyNavigation = createNavigation<Data>({
  // ...
  screens: {
    Login: {
      if: ({ isSignedIn }) => !isSignedIn,
      component: LoginScreen,
    },
    Home: {
      if: ({ isSignedIn }) => isSignedIn,
      component: HomeScreen,
    },
  },
});

export default function App() {
  const { isSignedIn } = useAuth();

  return <MyNavigation data={{ isSignedIn }} />;
}
@satya164
Copy link
Author

Very early prototype here react-navigation/react-navigation#11144

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment