Source profileQuality 92/100

agents-inc/skills/src/skills/mobile-navigation-react-navigation/SKILL.md

mobile-navigation-react-navigation

React Navigation 7+ patterns - static and dynamic APIs, type-safe navigation, stack/tab/drawer navigators, deep linking, authentication flows, screen preloading, header customization

Source repository stars
23
Declared platforms
0
Static risk flags
1
Last source update
2026-08-09
Source checked
2026-08-28

Decision brief

What it does: where it fits

Quick Guide: Use the static API for simpler TypeScript inference and automatic deep linking config. Use the dynamic API when you need runtime-dynamic screen lists. Always declare a global RootParamList for type-safe useNavigation everywhere. Use createNativeStackNavigator (not t…

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/agents-inc/skills --skill "src/skills/mobile-navigation-react-navigation"
    Safe inspection promptEditorial

    Inspect the Agent Skill "mobile-navigation-react-navigation" from https://github.com/agents-inc/skills/blob/81d43a51211aca12c85dcc16085fa99014ec548e/src/skills/mobile-navigation-react-navigation/SKILL.md at commit 81d43a51211aca12c85dcc16085fa99014ec548e. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      Pattern 1: Static API Setup

      The static API uses object configuration for simpler TypeScript and automatic deep linking.

      The static API uses object configuration for simpler TypeScript and automatic deep linking.Why good: types inferred from config (no manual ParamList), deep linking paths defined per-screen, less boilerplate than dynamic APISee examples/core.md for complete static API setup with groups and conditional screens.
    2. 02

      Pattern 2: Dynamic API Setup

      The dynamic API uses JSX components. Use when screen lists are runtime-dynamic.

      The dynamic API uses JSX components. Use when screen lists are runtime-dynamic.Why good: familiar JSX pattern, supports runtime-dynamic screen lists, manual param list gives explicit controlSee examples/core.md for dynamic API with typed hooks and nested navigators.
    3. 03

      CRITICAL: Before Using This Skill

      All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

      Setting up navigation structure (stack, tab, drawer) in a React Native appChoosing between static API and dynamic API for navigator configurationAdding type-safe navigation with TypeScript (param lists, typed hooks)
    4. 04

      Philosophy

      React Navigation provides routing and navigation for React Native apps. The key decision in v7 is static vs dynamic API:

      Static API -- object-based configuration. Simpler TypeScript (types inferred from config), automatic deep linking path generation, less boilerplate. Use for most apps.Dynamic API -- component-based configuration (/). Required when screen lists change at runtime or you need full programmatic control over navigator props. More verbose but more flexible.Native stack by default -- createNativeStackNavigator uses platform navigation primitives (UINavigationController/Fragment) for smoother transitions and lower memory. The JS stack (@react-navigation/stack) only when you…
    5. 05

      Core Patterns

      The static API uses object configuration for simpler TypeScript and automatic deep linking.

      The static API uses object configuration for simpler TypeScript and automatic deep linking.Why good: types inferred from config (no manual ParamList), deep linking paths defined per-screen, less boilerplate than dynamic APISee examples/core.md for complete static API setup with groups and conditional screens.

    Permission review

    Static risk signals and limitations

    Network access

    medium · line 266

    The documentation includes network, browsing, or remote request actions.

    linking={{ prefixes: ["myapp://", "https://myapp.com"] }}

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score92/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars23SourceRepository attention, not individual Skill quality
    Compatibility0 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    agents-inc/skills
    Skill path
    src/skills/mobile-navigation-react-navigation/SKILL.md
    Commit
    81d43a51211aca12c85dcc16085fa99014ec548e
    License
    MIT
    Collected
    2026-08-28
    Default branch
    main
    View the original SKILL.md

    React Navigation Patterns

    Quick Guide: Use the static API for simpler TypeScript inference and automatic deep linking config. Use the dynamic API when you need runtime-dynamic screen lists. Always declare a global RootParamList for type-safe useNavigation everywhere. Use createNativeStackNavigator (not the JS stack) for production performance. Auth flows use conditional screen rendering via the if callback (static) or conditional JSX (dynamic). Deep linking config lives per-screen in the static API -- no separate config object needed.


    <critical_requirements>

    CRITICAL: Before Using This Skill

    All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

    (You MUST declare a global ReactNavigation.RootParamList interface so useNavigation is type-safe without manual annotation)

    (You MUST use createNativeStackNavigator for production apps -- the JS stack (@react-navigation/stack) is significantly slower and only needed for highly custom transitions)

    (You MUST use popTo() to navigate back to a previous screen in the stack -- navigate() in v7 no longer pops back to existing screens)

    (You MUST wrap useFocusEffect callbacks in useCallback -- without it, the effect runs on every render, not just focus changes)

    (You MUST NOT use navigation.navigate('NestedScreen') to reach screens in child navigators -- v7 removed implicit nested navigation; use explicit parent targeting)

    </critical_requirements>


    Auto-detection: React Navigation, @react-navigation, createNativeStackNavigator, createBottomTabNavigator, createDrawerNavigator, createStaticNavigation, NavigationContainer, useNavigation, useRoute, useFocusEffect, usePreventRemove, StaticParamList, StaticScreenProps, NativeStackNavigationProp, CompositeNavigationProp, NavigatorScreenParams, deep linking, linking config, headerSearchBarOptions, headerLargeTitle, popTo, preload

    When to use:

    • Setting up navigation structure (stack, tab, drawer) in a React Native app
    • Choosing between static API and dynamic API for navigator configuration
    • Adding type-safe navigation with TypeScript (param lists, typed hooks)
    • Configuring deep linking (URL prefixes, path params, universal links)
    • Implementing authentication flows with conditional screen rendering
    • Customizing headers (large titles, search bars, custom buttons)
    • Preloading screens for perceived performance
    • Preventing back navigation for unsaved changes

    When NOT to use:

    • File-based routing with a managed workflow (uses its own router built on React Navigation)
    • Web-only React apps (use a web router)
    • Simple single-screen apps with no navigation

    Key patterns covered:

    • Static API vs dynamic API: when to use each
    • Global RootParamList declaration for type-safe hooks everywhere
    • Native stack vs JS stack performance trade-offs
    • Auth flow with conditional screens (static if callback or dynamic JSX)
    • Deep linking configuration (per-screen in static, linking prop in dynamic)
    • Screen preloading with navigation.preload()
    • useFocusEffect for screen lifecycle management
    • usePreventRemove for unsaved changes guards
    • Header customization: large titles, search bars, form sheets

    Detailed Resources:

    • examples/core.md - Static API setup, dynamic API setup, type-safe navigation, global RootParamList
    • examples/patterns.md - Auth flows, deep linking, modals, tab navigator with nested stacks
    • examples/advanced.md - Screen preloading, state persistence, usePreventRemove, useFocusEffect, header customization
    • reference.md - Decision frameworks, screen options cheat sheet, v6-to-v7 migration

    Philosophy

    React Navigation provides routing and navigation for React Native apps. The key decision in v7 is static vs dynamic API:

    • Static API -- object-based configuration. Simpler TypeScript (types inferred from config), automatic deep linking path generation, less boilerplate. Use for most apps.
    • Dynamic API -- component-based configuration (<Stack.Navigator>/<Stack.Screen>). Required when screen lists change at runtime or you need full programmatic control over navigator props. More verbose but more flexible.

    Both APIs produce the same navigation behavior -- the difference is configuration ergonomics.

    Core principles:

    1. Native stack by default -- createNativeStackNavigator uses platform navigation primitives (UINavigationController/Fragment) for smoother transitions and lower memory. The JS stack (@react-navigation/stack) only when you need custom transition animations not available natively.
    2. Type safety from the root -- Declare ReactNavigation.RootParamList globally so every useNavigation() call is type-checked without manual generics.
    3. Deep linking as first-class -- Configure linking per-screen (static API) or in a centralized config (dynamic API). Prefixes handle custom schemes and universal links.
    4. Screen lifecycle via focus -- Screens in a stack remain mounted when covered. Use useFocusEffect (not useEffect) for work that should pause when the screen loses focus.

    v7 behavioral changes from v6:

    • navigate() no longer pops back to existing screens -- use popTo() instead
    • Implicit nested navigator navigation removed -- must target parent screen explicitly
    • headerBackTitleVisible replaced with headerBackButtonDisplayMode
    • Navigation state is frozen in dev mode (mutations throw)
    • Theme objects now require a fonts property

    Core Patterns

    Pattern 1: Static API Setup

    The static API uses object configuration for simpler TypeScript and automatic deep linking.

    import { createStaticNavigation } from "@react-navigation/native";
    import { createNativeStackNavigator } from "@react-navigation/native-stack";
    import type { StaticParamList } from "@react-navigation/native";
    
    const RootStack = createNativeStackNavigator({
      initialRouteName: "Home",
      screenOptions: { headerShown: true },
      screens: {
        Home: HomeScreen,
        Profile: {
          screen: ProfileScreen,
          linking: "profile/:userId",
        },
      },
    });
    
    const Navigation = createStaticNavigation(RootStack);
    
    // Declare global types -- makes useNavigation() type-safe everywhere
    type RootStackParamList = StaticParamList<typeof RootStack>;
    declare global {
      namespace ReactNavigation {
        interface RootParamList extends RootStackParamList {}
      }
    }
    
    export function App() {
      return <Navigation />;
    }
    

    Why good: types inferred from config (no manual ParamList), deep linking paths defined per-screen, less boilerplate than dynamic API

    See examples/core.md for complete static API setup with groups and conditional screens.


    Pattern 2: Dynamic API Setup

    The dynamic API uses JSX components. Use when screen lists are runtime-dynamic.

    import { NavigationContainer } from "@react-navigation/native";
    import { createNativeStackNavigator } from "@react-navigation/native-stack";
    
    type RootStackParamList = {
      Home: undefined;
      Profile: { userId: string };
    };
    
    // Must declare globally for type-safe useNavigation()
    declare global {
      namespace ReactNavigation {
        interface RootParamList extends RootStackParamList {}
      }
    }
    
    const Stack = createNativeStackNavigator<RootStackParamList>();
    
    export function App() {
      return (
        <NavigationContainer>
          <Stack.Navigator initialRouteName="Home">
            <Stack.Screen name="Home" component={HomeScreen} />
            <Stack.Screen name="Profile" component={ProfileScreen} />
          </Stack.Navigator>
        </NavigationContainer>
      );
    }
    

    Why good: familiar JSX pattern, supports runtime-dynamic screen lists, manual param list gives explicit control

    See examples/core.md for dynamic API with typed hooks and nested navigators.


    Pattern 3: Type-Safe Navigation Hooks

    Declare RootParamList globally once, then useNavigation() and useRoute() are type-safe everywhere without manual generics.

    // In any screen component -- no generic needed
    function HomeScreen() {
      const navigation = useNavigation();
    
      // Type-checked: "Profile" must exist, params must match
      navigation.navigate("Profile", { userId: "123" });
    
      // Type error: "Nonexistent" is not in RootParamList
      navigation.navigate("Nonexistent"); // compile error
    }
    

    For nested navigators, use CompositeScreenProps or NavigatorScreenParams to propagate types. With the static API, use StaticScreenProps for screen component props.

    See examples/core.md for composite types and StaticScreenProps.


    Pattern 4: Authentication Flow

    Conditionally render auth or main screens. React Navigation animates the transition automatically.

    // Static API: use the `if` callback on groups
    const useIsAuthenticated = () => {
      const { isAuthenticated } = useContext(AuthContext);
      return isAuthenticated;
    };
    
    const useIsGuest = () => !useIsAuthenticated();
    
    const RootStack = createNativeStackNavigator({
      screens: {},
      groups: {
        Auth: {
          if: useIsGuest,
          screenOptions: { headerShown: false },
          screens: { Login: LoginScreen, Register: RegisterScreen },
        },
        Main: {
          if: useIsAuthenticated,
          screens: { Home: HomeScreen, Profile: ProfileScreen },
        },
      },
    });
    

    Why good: if callbacks cleanly separate auth/main screens, React Navigation handles transition animation, no manual state-based conditional rendering needed

    See examples/patterns.md for both static and dynamic auth flow implementations.


    Pattern 5: Deep Linking

    Static API: define linking per-screen. Dynamic API: pass a linking config to NavigationContainer.

    // Static API -- linking defined inline per screen
    const RootStack = createNativeStackNavigator({
      screens: {
        Home: { screen: HomeScreen, linking: "" },
        Profile: {
          screen: ProfileScreen,
          linking: {
            path: "user/:userId",
            parse: { userId: (id: string) => id.replace(/^@/, "") },
            stringify: { userId: (id: string) => `@${id}` },
          },
        },
      },
    });
    
    const Navigation = createStaticNavigation(RootStack);
    
    export function App() {
      return (
        <Navigation
          linking={{ prefixes: ["myapp://", "https://myapp.com"] }}
        />
      );
    }
    

    Why good: linking config co-located with screen definition, parse/stringify handle URL encoding, prefixes handle both custom scheme and universal links

    See examples/patterns.md for dynamic API linking, custom URL handlers, and platform-specific setup.


    Pattern 6: Native Stack vs JS Stack

    Which stack navigator?
    |-- Need custom JS-driven transition animations? --> @react-navigation/stack (JS)
    |-- Everything else --> @react-navigation/native-stack (NATIVE)
    
    FeatureNative StackJS Stack
    PerformanceNative animations, lower memoryJS-driven, higher overhead
    TransitionsPlatform defaults + limited customFully customizable
    Large titles (iOS)Supported nativelyNot available
    Search bar (iOS)headerSearchBarOptionsMust build custom
    Form sheetspresentation: "formSheet"Not available
    Gesture handlingNative, smoothJS-driven

    Default to native stack. Only use JS stack when you need transition animations that native stack cannot provide.


    Pattern 7: useFocusEffect for Screen Lifecycle

    Screens in a stack remain mounted when a new screen is pushed. Use useFocusEffect to run effects only when the screen is focused.

    import { useCallback } from "react";
    import { useFocusEffect } from "@react-navigation/native";
    
    function ChatScreen({ roomId }: { roomId: string }) {
      useFocusEffect(
        useCallback(() => {
          const ws = new WebSocket(`wss://chat.example.com/rooms/${roomId}`);
          // Cleanup runs when screen loses focus
          return () => ws.close();
        }, [roomId]),
      );
    }
    

    Gotcha: The callback MUST be wrapped in useCallback. Without it, the effect re-runs on every render, not just focus changes.

    See examples/advanced.md for polling, analytics tracking, and resource cleanup patterns.


    Pattern 8: Screen Preloading

    Preload heavy screens before the user navigates to them. The screen is rendered off-screen with all hooks running.

    function ProductList() {
      const navigation = useNavigation();
    
      const handleLongPress = (productId: string) => {
        navigation.preload("ProductDetail", { productId });
      };
      // Later: navigation.navigate("ProductDetail", { productId }) is instant
    }
    

    Limitations: Preloaded screens cannot dispatch navigation actions, update options, or listen to events until actually navigated to.


    Pattern 9: Header Customization

    Native stack supports platform-native header features: large titles, search bars, and form sheets.

    <Stack.Screen
      name="Settings"
      component={SettingsScreen}
      options={{
        headerLargeTitleEnabled: true,
        headerLargeStyle: { backgroundColor: "#f5f5f5" },
        headerSearchBarOptions: {
          placeholder: "Search settings...",
          onChangeText: (e) => handleSearch(e.nativeEvent.text),
          hideWhenScrolling: true,
        },
      }}
    />
    

    Gotcha: Custom header functions disable ALL native header features (large title, search bar, blur effects). Use headerLeft/headerRight to add custom elements while keeping native behavior.

    See examples/advanced.md for form sheets, custom header items, and search bar integration.


    <decision_framework>

    Decision Framework

    Static vs Dynamic API

    Starting a new navigation setup?
    |-- Can all screens be defined at build time?
    |   |-- YES --> Static API (simpler TS, auto deep linking)
    |   +-- NO  --> Dynamic API (runtime screen lists)
    |
    |-- Migrating incrementally from v6?
    |   +-- YES --> Dynamic API at root, static for new navigators
    |       (use getComponent() and createPathConfigForStaticNavigation)
    |
    |-- Need to wrap navigator with providers (e.g. context)?
    |   +-- Use static API with .with() method
    

    Navigator Type

    What navigation pattern?
    |-- Linear flow (onboarding, checkout) --> Stack Navigator
    |-- Main app sections with persistent bar --> Bottom Tab Navigator
    |-- Side menu / settings panel --> Drawer Navigator
    |-- Modal overlays --> Stack with presentation: "modal"
    |-- Bottom sheets --> Stack with presentation: "formSheet"
    |-- Combination --> Nest navigators (tabs inside stack, stacks inside tabs)
    

    Navigation Method

    How to move between screens?
    |-- Push new screen forward --> navigation.navigate("Screen", params)
    |-- Go back to specific screen --> navigation.popTo("Screen", params)
    |-- Go back one screen --> navigation.goBack()
    |-- Replace current screen --> navigation.replace("Screen", params)
    |-- Reset entire stack --> navigation.reset({ routes: [...] })
    |-- Navigate to nested screen --> navigation.navigate("Parent", { screen: "Child" })
    

    </decision_framework>


    <red_flags>

    RED FLAGS

    High Priority Issues:

    • Using navigate() to go back to a previous screen -- v7 changed behavior; navigate() stays on current screen if target exists. Use popTo() instead.
    • Using navigation.navigate("NestedScreen") to reach child navigator screens -- removed in v7. Must use navigate("ParentScreen", { screen: "NestedScreen" }).
    • Using JS stack (@react-navigation/stack) for production without a specific need for custom transitions -- native stack is significantly more performant.
    • Missing global RootParamList declaration -- every useNavigation() call is untyped, losing the primary benefit of TypeScript with React Navigation.
    • Using a custom header function and expecting native features (large title, search bar, blur) -- custom headers disable all native header functionality.

    Medium Priority Issues:

    • Inline component functions in <Stack.Screen component={() => <MyScreen />} /> -- creates a new component on every render, causing unmount/remount. Always pass a reference.
    • Not using useFocusEffect for screen-specific side effects -- useEffect runs even when the screen is covered by another screen in the stack.
    • Mutating navigation state directly (caught in dev mode in v7, silent corruption in prod).
    • Missing fonts property in custom theme -- required in v7, crashes without it.

    Gotchas & Edge Cases:

    • useFocusEffect callback must be wrapped in useCallback -- without it, the effect fires on every render, not just focus changes
    • usePreventRemove only fires for navigation state removal (back, pop, reset) -- it does NOT fire when the screen is merely unfocused (push, tab switch)
    • Preloaded screens cannot dispatch navigation actions or call navigation.setOptions() until actually navigated to
    • Screen options can be an object or a function receiving { route, navigation } -- use the function form when options depend on route params
    • headerSearchBarOptions requires contentInsetAdjustmentBehavior="automatic" on your ScrollView/FlatList for proper layout
    • headerBackButtonDisplayMode replaced headerBackTitleVisible in v7 -- values are "default", "generic", or "minimal"
    • unmountOnBlur removed from tabs/drawer in v7 -- use popToTopOnBlur: true or the useIsFocused pattern instead
    • Navigation state frozen in dev mode -- if you were mutating state directly, you'll get runtime errors in v7 dev builds
    • Android requires RNScreensFragmentFactory setup in MainActivity -- without it, View state is lost during Activity restarts
    • The Link component changed from path-based to screen-based: <Link screen="Profile" params={{ userId }}> not <Link to="/profile/123">

    </red_flags>


    <critical_reminders>

    CRITICAL REMINDERS

    All code must follow project conventions in CLAUDE.md

    (You MUST declare a global ReactNavigation.RootParamList interface so useNavigation is type-safe without manual annotation)

    (You MUST use createNativeStackNavigator for production apps -- the JS stack (@react-navigation/stack) is significantly slower and only needed for highly custom transitions)

    (You MUST use popTo() to navigate back to a previous screen in the stack -- navigate() in v7 no longer pops back to existing screens)

    (You MUST wrap useFocusEffect callbacks in useCallback -- without it, the effect runs on every render, not just focus changes)

    (You MUST NOT use navigation.navigate('NestedScreen') to reach screens in child navigators -- v7 removed implicit nested navigation; use explicit parent targeting)

    Failure to follow these rules will cause untyped navigation, performance issues, broken back navigation, and runtime errors.

    </critical_reminders>

    Frequently asked questions

    What to verify before installation and use

    What does the mobile-navigation-react-navigation source document cover?

    Quick Guide: Use the static API for simpler TypeScript inference and automatic deep linking config. Use the dynamic API when you need runtime-dynamic screen lists. Always declare a global RootParamList for type-safe useNavigation everywhere. Use createNativeStackNavigator (not t…

    How do I install mobile-navigation-react-navigation?

    The source record exposes this install command: npx skills add https://github.com/agents-inc/skills --skill "src/skills/mobile-navigation-react-navigation". Inspect the command and pinned source before running it.

    Which permission-related actions were detected?

    Static rules flagged network in the source; the page lists the matching lines and excerpts.

    Alternatives

    Compare before choosing

    Computed 1009

    event4u-app/agent-config

    existing-ui-audit

    Use BEFORE writing or editing any non-trivial UI — inventories components, design tokens, shadcn primitives, and reusable patterns into state.ui_audit. Hard gate for the ui directive set.

    Computed 97150

    UiPath/skills

    uipath-coded-apps

    UiPath Coded Apps — scaffold, build, run, and deploy Coded Web Apps and Coded Action Apps: React/TypeScript apps that call UiPath Cloud APIs via the `@uipath/uipath-typescript` SDK and ship to Automation Cloud (push/pull to Studio Web, pack, publish, deploy, OAuth-PKCE). Also generates live analytics & governance dashboards from a plain-language request, wired to tenant data via the Insights real-time API, with edit and deploy flows. For RPA→uipath-rpa, Python agents→uipath-agents, Maestro flows

    Computed 961,113

    fcakyon/claude-codex-settings

    vercel-react-view-transitions

    Guide for implementing smooth, native-feeling animations using React's View Transition API (`<ViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter/exit of components, animate list reorder, implement directional (forward/back) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view

    Computed 96224

    yonatangross/orchestkit

    json-render-catalog

    json-render component catalog patterns for AI-safe generative UI. Define Zod-typed catalogs that constrain what AI can generate, use @json-render/shadcn for 36 pre-built components, optimize specs with YAML mode, and apply the three edit modes (patch/merge/diff) for progressive updates. Use when building AI-generated UIs, defining component catalogs, or integrating json-render into React/Vue/Svelte/React Native/Ink/Next.js projects.