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.
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
}}
/>
);
}
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> {}
}
}
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 }} />;
}
Very early prototype here react-navigation/react-navigation#11144