Native stack navigator for React Native applications that uses react-native-screens under the hood to deliver optimal performance by leveraging native navigation primitives.
—
Navigation properties, screen props, event handling, and utility hooks for accessing navigation state and header information in native stack navigators.
Props provided to screen components with navigation and route information.
/**
* Props provided to each screen component
*/
type NativeStackScreenProps<
ParamList extends ParamListBase,
RouteName extends keyof ParamList = string,
NavigatorID extends string | undefined = undefined
> = {
navigation: NativeStackNavigationProp<ParamList, RouteName, NavigatorID>;
route: RouteProp<ParamList, RouteName>;
};Usage Examples:
import { NativeStackScreenProps } from "@react-navigation/native-stack";
type RootStackParamList = {
Profile: { userId: string };
Settings: undefined;
};
type ProfileScreenProps = NativeStackScreenProps<RootStackParamList, 'Profile'>;
function ProfileScreen({ navigation, route }: ProfileScreenProps) {
const { userId } = route.params;
return (
<View>
<Text>User ID: {userId}</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}The navigation prop provides methods for navigating between screens and stack manipulation.
/**
* Navigation prop with native stack-specific methods
*/
type NativeStackNavigationProp<
ParamList extends ParamListBase,
RouteName extends keyof ParamList = string,
NavigatorID extends string | undefined = undefined
> = NavigationProp<
ParamList,
RouteName,
NavigatorID,
StackNavigationState<ParamList>,
NativeStackNavigationOptions,
NativeStackNavigationEventMap
> & StackActionHelpers<ParamList>;
/**
* Core navigation methods available on navigation prop
*/
interface NavigationMethods<ParamList extends ParamListBase> {
navigate<RouteName extends keyof ParamList>(
name: RouteName,
params?: ParamList[RouteName]
): void;
push<RouteName extends keyof ParamList>(
name: RouteName,
params?: ParamList[RouteName]
): void;
pop(count?: number): void;
popToTop(): void;
goBack(): void;
canGoBack(): boolean;
replace<RouteName extends keyof ParamList>(
name: RouteName,
params?: ParamList[RouteName]
): void;
setOptions(options: Partial<NativeStackNavigationOptions>): void;
setParams(params: Partial<ParamList[RouteName]>): void;
addListener(type: string, callback: Function): Function;
removeListener(type: string, callback: Function): void;
isFocused(): boolean;
}Navigation Methods Examples:
function HomeScreen({ navigation }: NativeStackScreenProps<RootStackParamList, 'Home'>) {
const handleNavigation = () => {
// Navigate to a screen
navigation.navigate('Profile', { userId: '123' });
// Push a new screen (allows multiple instances)
navigation.push('Details', { itemId: 456 });
// Go back
navigation.goBack();
// Pop to root
navigation.popToTop();
// Replace current screen
navigation.replace('Login');
// Update screen options dynamically
navigation.setOptions({
title: 'Updated Title',
headerRight: () => <Button title="Save" onPress={save} />,
});
};
return (
// Screen content
);
}Event system for responding to navigation state changes and transitions.
/**
* Native stack-specific navigation events
*/
interface NativeStackNavigationEventMap {
/**
* Event fired when a transition animation starts
*/
transitionStart: { data: { closing: boolean } };
/**
* Event fired when a transition animation ends
*/
transitionEnd: { data: { closing: boolean } };
/**
* Event fired when a swipe back gesture is cancelled on iOS
*/
gestureCancel: { data: undefined };
/**
* Event fired when sheet presentation detent changes
*/
sheetDetentChange: { data: { index: number; stable: boolean } };
}Event Handling Examples:
function ScreenWithEvents({ navigation }: NativeStackScreenProps<RootStackParamList, 'Home'>) {
React.useEffect(() => {
// Listen for transition events
const unsubscribeTransitionStart = navigation.addListener('transitionStart', (e) => {
console.log('Transition started:', e.data.closing ? 'closing' : 'opening');
});
const unsubscribeTransitionEnd = navigation.addListener('transitionEnd', (e) => {
console.log('Transition ended:', e.data.closing ? 'closed' : 'opened');
});
// Listen for sheet detent changes
const unsubscribeSheetDetent = navigation.addListener('sheetDetentChange', (e) => {
console.log('Sheet detent changed to index:', e.data.index, 'stable:', e.data.stable);
});
return () => {
unsubscribeTransitionStart();
unsubscribeTransitionEnd();
unsubscribeSheetDetent();
};
}, [navigation]);
return (
// Screen content
);
}Props provided to dynamic screen options functions.
/**
* Arguments provided to screen options functions
*/
type NativeStackOptionsArgs<
ParamList extends ParamListBase,
RouteName extends keyof ParamList = keyof ParamList,
NavigatorID extends string | undefined = undefined
> = NativeStackScreenProps<ParamList, RouteName, NavigatorID> & {
theme: Theme;
};Dynamic Options Examples:
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={({ route, navigation, theme }: NativeStackOptionsArgs<RootStackParamList, 'Profile'>) => ({
title: route.params?.name || 'Profile',
headerStyle: { backgroundColor: theme.colors.primary },
headerRight: ({ tintColor }) => (
<TouchableOpacity onPress={() => navigation.navigate('EditProfile')}>
<Icon name="edit" color={tintColor} />
</TouchableOpacity>
),
})}
/>Hook for accessing animated header height values for custom scroll behaviors.
/**
* Hook to get the animated header height value
* Must be used within a screen in a native stack navigator
* @returns Animated value representing the header height
* @throws Error if used outside of native stack navigator context with message:
* "Couldn't find the header height. Are you inside a screen in a native stack navigator?"
*/
function useAnimatedHeaderHeight(): Animated.AnimatedInterpolation<number>;
/**
* Context that provides the animated header height value
* Used internally by useAnimatedHeaderHeight hook
*/
const AnimatedHeaderHeightContext: React.Context<Animated.AnimatedInterpolation<number> | undefined>;Usage Examples:
import { useAnimatedHeaderHeight } from "@react-navigation/native-stack";
import { Animated } from "react-native";
function ScrollScreen() {
const headerHeight = useAnimatedHeaderHeight();
const scrollY = new Animated.Value(0);
// Use header height in animations
const headerOpacity = scrollY.interpolate({
inputRange: [0, headerHeight],
outputRange: [1, 0],
extrapolate: 'clamp',
});
return (
<Animated.ScrollView
contentInsetAdjustmentBehavior="automatic"
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: scrollY } } }],
{ useNativeDriver: false }
)}
scrollEventThrottle={16}
>
<Animated.View style={{ opacity: headerOpacity }}>
{/* Content that fades based on scroll */}
</Animated.View>
</Animated.ScrollView>
);
}Route information provided to screen components.
/**
* Route prop containing screen parameters and metadata
*/
interface RouteProp<ParamList extends ParamListBase, RouteName extends keyof ParamList> {
key: string;
name: RouteName;
params: ParamList[RouteName];
path?: string;
}Route Usage Examples:
function DetailScreen({ route }: { route: RouteProp<RootStackParamList, 'Detail'> }) {
const { itemId, category } = route.params;
return (
<View>
<Text>Screen: {route.name}</Text>
<Text>Item ID: {itemId}</Text>
<Text>Category: {category}</Text>
<Text>Route Key: {route.key}</Text>
</View>
);
}type ParamListBase = Record<string, object | undefined>;
interface Theme {
dark: boolean;
colors: {
primary: string;
background: string;
card: string;
text: string;
border: string;
notification: string;
};
}
interface StackNavigationState<ParamList extends ParamListBase> {
key: string;
index: number;
routeNames: string[];
history?: unknown[];
routes: Route<keyof ParamList>[];
type: string;
stale: false;
}
interface Route<RouteName = string> {
key: string;
name: RouteName;
params?: object;
path?: string;
}Install with Tessl CLI
npx tessl i tessl/npm-react-navigation--native-stack