CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-native-screens

Native navigation primitives for React Native apps with native screen management and transitions.

Pending
Overview
Eval results
Files

navigation-utilities.mddocs/

Navigation Utilities

Utility functions, hooks, and configuration objects that provide additional navigation behavior and integration capabilities. These utilities enhance the core screen functionality with platform-specific features and performance optimizations.

Core Imports

import {
  executeNativeBackPress,
  isSearchBarAvailableForCurrentPlatform,
  useTransitionProgress,
  ScreenContext,
  compatibilityFlags,
  featureFlags
} from "react-native-screens";

Capabilities

Native Back Press

Executes the native back press behavior on Android, which typically exits the application or navigates to the previous activity.

/**
 * Executes native back press behavior, exits the app on Android
 * @returns Always returns true to indicate the event was handled
 */
function executeNativeBackPress(): boolean;

Usage Example:

import { executeNativeBackPress } from "react-native-screens";
import { BackHandler, Platform } from "react-native";

// Custom back handler that can exit the app
function handleBackPress() {
  // Perform custom logic
  if (canExit) {
    if (Platform.OS === 'android') {
      return executeNativeBackPress();
    }
  }
  return false; // Let default behavior handle it
}

// Register back handler
BackHandler.addEventListener('hardwareBackPress', handleBackPress);

Platform Behavior:

  • Android: Exits the application or navigates to previous activity
  • iOS: No effect (iOS doesn't have a hardware back button)
  • Return Value: Always returns true to indicate the event was handled

Search Bar Availability

Boolean constant indicating whether the SearchBar component is available on the current platform.

/**
 * Boolean indicating if SearchBar is available on the current platform
 */
const isSearchBarAvailableForCurrentPlatform: boolean;

Usage Example:

import { 
  isSearchBarAvailableForCurrentPlatform, 
  SearchBar 
} from "react-native-screens";

function ConditionalSearchScreen() {
  return (
    <View>
      {isSearchBarAvailableForCurrentPlatform ? (
        <SearchBar placeholder="Search..." />
      ) : (
        <TextInput placeholder="Search..." />
      )}
    </View>
  );
}

Platform Support:

  • iOS: true - Native UISearchController integration
  • Android: true - Material Design search view
  • Web/Other platforms: false - Use fallback components

Transition Progress Hook

Hook that provides transition progress information for native stack screens. Allows for custom animations and UI updates based on screen transition state.

/**
 * Hook that provides transition progress information for native stack screens
 * @returns Transition progress context value with animation data
 * @throws Error if used outside a native stack screen
 */
function useTransitionProgress(): TransitionProgressContext;

interface TransitionProgressContext {
  /** Current transition progress (0-1) */
  progress: Animated.Value;
  
  /** Whether the screen is being closed (0 or 1) */
  closing: Animated.Value;
  
  /** Whether navigation is going forward (0 or 1) */  
  goingForward: Animated.Value;
}

Usage Example:

import React from 'react';
import { useTransitionProgress } from "react-native-screens";
import { Animated } from 'react-native';

function AnimatedScreen() {
  const { progress, closing, goingForward } = useTransitionProgress();

  const scale = progress.interpolate({
    inputRange: [0, 1],
    outputRange: [0.8, 1],
  });
  
  const opacity = progress.interpolate({
    inputRange: [0, 1],  
    outputRange: [0, 1],
  });

  return (
    <Animated.View style={[
      { flex: 1 },
      {
        transform: [{ scale }],
        opacity,
      }
    ]}>
      {/* Screen content */}
    </Animated.View>
  );
}

Advanced Usage:

import React from 'react';
import { useTransitionProgress } from "react-native-screens";
import { Animated, View } from 'react-native';

function ComplexTransitionScreen() {
  const { progress, closing, goingForward } = useTransitionProgress();

  // Different animations for push vs pop
  const headerTranslateY = Animated.multiply(
    goingForward,
    progress.interpolate({
      inputRange: [0, 1],
      outputRange: [-50, 0],
    })
  );
  
  const contentOpacity = progress.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 1],
  });

  return (
    <View style={{ flex: 1 }}>
      <Animated.View style={[
        { height: 60, backgroundColor: '#007AFF' },
        { transform: [{ translateY: headerTranslateY }] }
      ]} />
      <Animated.View style={[
        { flex: 1 },
        { opacity: contentOpacity }
      ]}>
        {/* Screen content */}
      </Animated.View>
    </View>
  );
}

Screen Context

React context that allows swapping the Screen component implementation. This is primarily used for enhanced integrations like Reanimated support.

/**
 * React context for swapping Screen component implementation
 */
const ScreenContext: React.Context<React.ComponentType<ScreenProps>>;

Usage Example:

import React from 'react';
import { ScreenContext, InnerScreen } from "react-native-screens";
import { CustomReanimatedScreen } from './CustomReanimatedScreen';

// Provider that allows using enhanced screen implementation
function EnhancedScreenProvider({ children, useReanimatedScreen = false }) {
  const ScreenImplementation = useReanimatedScreen ? CustomReanimatedScreen : InnerScreen;
  
  return (
    <ScreenContext.Provider value={ScreenImplementation}>
      {children}
    </ScreenContext.Provider>
  );
}

// Consumer that uses the context
function ScreenConsumer(props) {
  const ScreenWrapper = React.useContext(ScreenContext) || InnerScreen;
  
  return <ScreenWrapper {...props} />;
}

Note: This context is primarily used internally and for advanced integrations. Most applications should use the standard Screen component directly.

Compatibility Flags

Configuration object that exposes compatibility information for downstream navigation libraries to detect feature availability and maintain backward compatibility.

/**
 * Exposes compatibility information for downstream navigation libraries
 */
const compatibilityFlags: CompatibilityFlags;

interface CompatibilityFlags {
  /** Indicates new back title implementation (v3.21+) */
  isNewBackTitleImplementation: boolean;
  
  /** Indicates new header implementation (v4.0+) */
  usesHeaderFlexboxImplementation: boolean;
}

Usage Example:

import { compatibilityFlags } from "react-native-screens";

// Library code that needs to handle different versions
function configureHeaderLayout() {
  if (compatibilityFlags.usesHeaderFlexboxImplementation) {
    // Use new flexbox-based header layout
    return { flex: 1, justifyContent: 'center' };
  } else {
    // Use legacy header layout
    return { position: 'absolute', top: 0, left: 0, right: 0 };
  }
}

function configureBackButton() {
  if (compatibilityFlags.isNewBackTitleImplementation) {
    // Use new back title system
    return { backTitle: 'Back', backTitleVisible: true };
  } else {
    // Use legacy back button handling
    return { backButtonTitle: 'Back' };
  }
}

Feature Flags

Configuration object for controlling experimental and stable features globally across the application.

/**
 * Configurable global behavior flags
 */
const featureFlags: FeatureFlags;

interface FeatureFlags {
  /** Experimental feature flags */
  experiment: {
    /** Experimental bottom tabs control */
    controlledBottomTabs: boolean;
  };
  
  /** Stable configuration flags (currently empty) */
  stable: {};
}

Usage Example:

import { featureFlags } from "react-native-screens";

// Enable experimental bottom tabs
featureFlags.experiment.controlledBottomTabs = true;

// Check if experimental features are enabled
function useExperimentalBottomTabs() {
  return featureFlags.experiment.controlledBottomTabs;
}

function ConditionalBottomTabs() {
  if (useExperimentalBottomTabs()) {
    return <ExperimentalBottomTabs />;
  }
  
  return <StandardBottomTabs />;
}

Integration Patterns

React Navigation Integration

import { useTransitionProgress } from "react-native-screens";
import { useRoute, useNavigation } from "@react-navigation/native";

function ReactNavigationIntegration() {
  const route = useRoute();
  const navigation = useNavigation();
  
  // Use transition progress for custom animations
  const { progress } = useTransitionProgress();
  
  // Combine with React Navigation hooks
  const isScreenFocused = navigation.isFocused();
  
  return (
    <View>
      <Text>Route: {route.name}</Text>
      <Text>Focused: {isScreenFocused ? 'Yes' : 'No'}</Text>
    </View>
  );
}

Custom Navigation System

import { 
  executeNativeBackPress,
  useTransitionProgress,
  ScreenContext
} from "react-native-screens";

function CustomNavigationSystem({ children }) {
  const handleBackPress = useCallback(() => {
    // Custom back handling logic
    if (canGoBack) {
      goBack();
      return true;
    }
    
    // Exit app on Android
    return executeNativeBackPress();
  }, [canGoBack, goBack]);

  return (
    <ScreenContext.Provider value={{ isActive: true, screenId: 'custom' }}>
      {children}
    </ScreenContext.Provider>
  );
}

Performance Monitoring

import { useTransitionProgress } from "react-native-screens";

function PerformanceMonitor() {
  const { progress } = useTransitionProgress();
  
  useEffect(() => {
    const listener = progress.addListener(({ value }) => {
      // Monitor transition performance
      console.log('Transition progress:', value);
      
      if (value === 1) {
        console.log('Transition completed');
        // Log performance metrics
      }
    });
    
    return () => progress.removeListener(listener);
  }, [progress]);
  
  return null;
}

Platform-Specific Utilities

Android Back Button Handling

import { executeNativeBackPress } from "react-native-screens";
import { BackHandler, Platform } from "react-native";

function setupAndroidBackHandler() {
  if (Platform.OS !== 'android') return;
  
  const handleBackPress = () => {
    // Custom logic before exiting
    if (shouldExit()) {
      executeNativeBackPress();
      return true;
    }
    return false;
  };
  
  BackHandler.addEventListener('hardwareBackPress', handleBackPress);
  
  return () => {
    BackHandler.removeEventListener('hardwareBackPress', handleBackPress);
  };
}

iOS Search Integration

import { 
  isSearchBarAvailableForCurrentPlatform,
  SearchBar 
} from "react-native-screens";

function iOSSearchIntegration() {
  if (!isSearchBarAvailableForCurrentPlatform) {
    return null;
  }
  
  return (
    <SearchBar
      placeholder="Search..."
      placement="stacked"
      hideWhenScrolling={true}
    />
  );
}

Error Handling

Context Validation

import { ScreenContext } from "react-native-screens";

function useScreenContext() {
  const context = useContext(ScreenContext);
  
  if (!context) {
    throw new Error(
      'useScreenContext must be used within a Screen component'
    );
  }
  
  return context;
}

Hook Safety

import { useTransitionProgress } from "react-native-screens";

function SafeTransitionHook() {
  try {
    const progress = useTransitionProgress();
    return progress;
  } catch (error) {
    console.warn('useTransitionProgress called outside native stack screen');
    return null;
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-react-native-screens

docs

core-functions.md

experimental-features.md

header-components.md

index.md

navigation-utilities.md

screen-components.md

types-interfaces.md

tile.json