Skip to main content

Overview

The useScreenState hook provides access to navigation state, screen information, and stack context without animation values. Use this hook when you need to access route information, screen index, or navigation object without triggering animations.

Import

import { useScreenState } from 'react-native-screen-transitions';

Usage

import { useScreenState } from 'react-native-screen-transitions';

function DetailScreen() {
  const { index, focusedRoute, routes, navigation, snapTo } = useScreenState();

  console.log('Current screen index:', index);
  console.log('Total screens:', routes.length);
  console.log('Focused route name:', focusedRoute.name);

  return (
    <View>
      <Text>Screen {index + 1} of {routes.length}</Text>
      <Button title="Go Back" onPress={() => navigation.goBack()} />
    </View>
  );
}

Return Value

Returns a ScreenState object with the following properties:
index
number
The index of this screen in the stack (0-based).
focusedIndex
number
Index of the currently focused (topmost) screen in the stack.
focusedRoute
Route<string>
Route object of the currently focused screen in the stack.Properties:
  • key (string): Unique key for this route
  • name (string): Route name
  • params (object): Route parameters
routes
Route<string>[]
Array of all routes currently in the stack.
options
ScreenTransitionConfig
Screen options for the currently focused screen, including all transition configuration.
navigation
BaseStackNavigation
Navigation object for this screen. Provides methods like navigate(), goBack(), push(), etc.
meta
Record<string, unknown> | undefined
Custom metadata from the focused screen’s options. Use this to pass custom data between screens.
snapTo
(index: number) => void
Programmatically snap the focused screen to a snap point index. Only works if the screen has snapPoints configured.Scoped to this screen’s stack context, avoiding global history ambiguity.

Examples

Display Stack Position

import { useScreenState } from 'react-native-screen-transitions';

function MyScreen() {
  const { index, routes } = useScreenState();

  return (
    <View>
      <Text>Screen {index + 1} of {routes.length}</Text>
      <Text>Can go back: {index > 0 ? 'Yes' : 'No'}</Text>
    </View>
  );
}

Access Route Parameters

import { useScreenState } from 'react-native-screen-transitions';

function ProfileScreen() {
  const { focusedRoute } = useScreenState();
  const userId = focusedRoute.params?.userId;

  return (
    <View>
      <Text>User ID: {userId}</Text>
    </View>
  );
}

Control Snap Points

import { useScreenState } from 'react-native-screen-transitions';
import { Button, View } from 'react-native';

function BottomSheet() {
  const { snapTo } = useScreenState();

  return (
    <View>
      <Button title="Collapse to 50%" onPress={() => snapTo(0)} />
      <Button title="Expand to 100%" onPress={() => snapTo(1)} />
    </View>
  );
}

Conditional Rendering Based on Stack

import { useScreenState } from 'react-native-screen-transitions';

function MyScreen() {
  const { index, routes } = useScreenState();
  const isFirstScreen = index === 0;
  const isLastScreen = index === routes.length - 1;

  return (
    <View>
      {!isFirstScreen && <BackButton />}
      {isLastScreen && <Text>Last screen in stack</Text>}
    </View>
  );
}

Use Custom Metadata

// In screen options:
<Stack.Screen
  name="Detail"
  options={{ meta: { hideTabBar: true, theme: 'dark' } }}
/>

// In component:
import { useScreenState } from 'react-native-screen-transitions';

function MyComponent() {
  const { meta } = useScreenState();
  
  if (meta?.hideTabBar) {
    // Hide tab bar logic
  }
  
  const theme = meta?.theme ?? 'light';
  
  return <View style={{ backgroundColor: theme === 'dark' ? '#000' : '#fff' }} />;
}
import { useScreenState } from 'react-native-screen-transitions';

function ListScreen() {
  const { navigation, index } = useScreenState();

  const handleItemPress = (itemId: string) => {
    navigation.push('Detail', { id: itemId });
  };

  const handleBack = () => {
    if (index > 0) {
      navigation.goBack();
    }
  };

  return (
    <View>
      <FlatList
        data={items}
        renderItem={({ item }) => (
          <Pressable onPress={() => handleItemPress(item.id)}>
            <Text>{item.name}</Text>
          </Pressable>
        )}
      />
      {index > 0 && <Button title="Back" onPress={handleBack} />}
    </View>
  );
}

TypeScript

You can type the navigation object by passing a generic parameter:
import { useScreenState } from 'react-native-screen-transitions';
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';

type RootStackParamList = {
  Home: undefined;
  Detail: { id: string };
  Profile: { userId: number };
};

type Navigation = NativeStackNavigationProp<RootStackParamList>;

function MyScreen() {
  const { navigation } = useScreenState<Navigation>();
  
  // TypeScript will autocomplete route names and validate params
  navigation.navigate('Detail', { id: '123' });
  
  return <View />;
}

Notes

Use useScreenState when you need navigation state without triggering animations. For animated values, use useScreenAnimation instead.
The snapTo function is scoped to the current stack context, so it will only work for screens in the same stack.
The meta property is useful for passing custom configuration between screens without polluting route params. It’s also accessible in screenStyleInterpolator for conditional animation logic.