jutsu-react-native:react-native-navigation

React Native Navigation

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "jutsu-react-native:react-native-navigation" with this command: npx skills add thebushidocollective/han/thebushidocollective-han-jutsu-react-native-react-native-navigation

React Native Navigation

Use this skill when implementing navigation in React Native applications using React Navigation (the de facto standard navigation library).

Key Concepts

Installation

npm install @react-navigation/native npm install react-native-screens react-native-safe-area-context

For stack navigation

npm install @react-navigation/native-stack

For tab navigation

npm install @react-navigation/bottom-tabs

For drawer navigation

npm install @react-navigation/drawer react-native-gesture-handler react-native-reanimated

Basic Setup

import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack';

type RootStackParamList = { Home: undefined; Details: { itemId: string }; };

const Stack = createNativeStackNavigator<RootStackParamList>();

export default function App() { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Details" component={DetailsScreen} /> </Stack.Navigator> </NavigationContainer> ); }

Stack Navigation

The most common navigation pattern:

import React from 'react'; import { View, Text, Button } from 'react-native'; import { NativeStackScreenProps } from '@react-navigation/native-stack';

type RootStackParamList = { Home: undefined; Details: { itemId: string; title: string }; };

type HomeProps = NativeStackScreenProps<RootStackParamList, 'Home'>; type DetailsProps = NativeStackScreenProps<RootStackParamList, 'Details'>;

function HomeScreen({ navigation }: HomeProps) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home Screen</Text> <Button title="Go to Details" onPress={() => navigation.navigate('Details', { itemId: '123', title: 'My Item', }) } /> </View> ); }

function DetailsScreen({ route, navigation }: DetailsProps) { const { itemId, title } = route.params;

return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Details Screen</Text> <Text>Item ID: {itemId}</Text> <Text>Title: {title}</Text> <Button title="Go Back" onPress={() => navigation.goBack()} /> </View> ); }

Tab Navigation

Bottom tabs for primary navigation:

import React from 'react'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { Ionicons } from '@expo/vector-icons';

type TabParamList = { Home: undefined; Search: undefined; Profile: undefined; };

const Tab = createBottomTabNavigator<TabParamList>();

export default function TabNavigator() { return ( <Tab.Navigator screenOptions={({ route }) => ({ tabBarIcon: ({ focused, color, size }) => { let iconName: keyof typeof Ionicons.glyphMap;

      if (route.name === 'Home') {
        iconName = focused ? 'home' : 'home-outline';
      } else if (route.name === 'Search') {
        iconName = focused ? 'search' : 'search-outline';
      } else {
        iconName = focused ? 'person' : 'person-outline';
      }

      return &#x3C;Ionicons name={iconName} size={size} color={color} />;
    },
    tabBarActiveTintColor: '#007AFF',
    tabBarInactiveTintColor: 'gray',
  })}
>
  &#x3C;Tab.Screen name="Home" component={HomeScreen} />
  &#x3C;Tab.Screen name="Search" component={SearchScreen} />
  &#x3C;Tab.Screen name="Profile" component={ProfileScreen} />
&#x3C;/Tab.Navigator>

); }

Best Practices

Type-Safe Navigation

Define navigation types for type safety:

import { NativeStackScreenProps } from '@react-navigation/native-stack';

// Define param list type RootStackParamList = { Home: undefined; Details: { itemId: string }; UserProfile: { userId: string; name: string }; };

// Declare global types declare global { namespace ReactNavigation { interface RootParamList extends RootStackParamList {} } }

// Use typed props type DetailsProps = NativeStackScreenProps<RootStackParamList, 'Details'>;

function DetailsScreen({ route, navigation }: DetailsProps) { // route.params is fully typed const { itemId } = route.params;

// navigation.navigate is type-safe navigation.navigate('UserProfile', { userId: '123', name: 'John', });

return <View />; }

Header Customization

Customize navigation headers:

<Stack.Navigator screenOptions={{ headerStyle: { backgroundColor: '#007AFF', }, headerTintColor: '#fff', headerTitleStyle: { fontWeight: 'bold', }, }}

<Stack.Screen name="Home" component={HomeScreen} options={{ title: 'My Home', headerRight: () => ( <Button onPress={() => console.log('Pressed')} title="Info" color="#fff" /> ), }} /> </Stack.Navigator>

Dynamic Header Options

Set header options from screen:

import { useLayoutEffect } from 'react';

function DetailsScreen({ navigation, route }: DetailsProps) { useLayoutEffect(() => { navigation.setOptions({ title: route.params.title, headerRight: () => ( <Button title="Save" onPress={() => console.log('Save')} /> ), }); }, [navigation, route.params.title]);

return <View />; }

Nested Navigators

Combine different navigation patterns:

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { createNativeStackNavigator } from '@react-navigation/native-stack';

const HomeStack = createNativeStackNavigator(); const ProfileStack = createNativeStackNavigator(); const Tab = createBottomTabNavigator();

function HomeStackScreen() { return ( <HomeStack.Navigator> <HomeStack.Screen name="Home" component={HomeScreen} /> <HomeStack.Screen name="Details" component={DetailsScreen} /> </HomeStack.Navigator> ); }

function ProfileStackScreen() { return ( <ProfileStack.Navigator> <ProfileStack.Screen name="Profile" component={ProfileScreen} /> <ProfileStack.Screen name="Settings" component={SettingsScreen} /> </ProfileStack.Navigator> ); }

export default function App() { return ( <NavigationContainer> <Tab.Navigator> <Tab.Screen name="HomeTab" component={HomeStackScreen} /> <Tab.Screen name="ProfileTab" component={ProfileStackScreen} /> </Tab.Navigator> </NavigationContainer> ); }

Common Patterns

Authentication Flow

import React, { useState } from 'react'; import { createNativeStackNavigator } from '@react-navigation/native-stack';

type RootStackParamList = { SignIn: undefined; SignUp: undefined; Home: undefined; Details: { itemId: string }; };

const Stack = createNativeStackNavigator<RootStackParamList>();

export default function App() { const [isSignedIn, setIsSignedIn] = useState(false);

return ( <NavigationContainer> <Stack.Navigator> {!isSignedIn ? ( // Auth screens <> <Stack.Screen name="SignIn" component={SignInScreen} /> <Stack.Screen name="SignUp" component={SignUpScreen} /> </> ) : ( // App screens <> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Details" component={DetailsScreen} /> </> )} </Stack.Navigator> </NavigationContainer> ); }

Deep Linking

Configure deep linking:

import { NavigationContainer } from '@react-navigation/native';

const linking = { prefixes: ['myapp://', 'https://myapp.com'], config: { screens: { Home: 'home', Details: 'details/:itemId', UserProfile: 'user/:userId', }, }, };

export default function App() { return ( <NavigationContainer linking={linking}> <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Details" component={DetailsScreen} /> <Stack.Screen name="UserProfile" component={UserProfileScreen} /> </Stack.Navigator> </NavigationContainer> ); }

Modal Navigation

Present screens as modals:

<Stack.Navigator> <Stack.Group> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Details" component={DetailsScreen} /> </Stack.Group> <Stack.Group screenOptions={{ presentation: 'modal' }}> <Stack.Screen name="CreatePost" component={CreatePostScreen} /> <Stack.Screen name="Settings" component={SettingsScreen} /> </Stack.Group> </Stack.Navigator>

Navigation Guards

Protect routes with guards:

import { useEffect } from 'react';

function ProtectedScreen({ navigation }: any) { const isAuthenticated = useAuth(); // Custom hook

useEffect(() => { if (!isAuthenticated) { navigation.replace('SignIn'); } }, [isAuthenticated, navigation]);

if (!isAuthenticated) { return null; // Or loading screen }

return <View>{/* Protected content */}</View>; }

Custom Tab Bar

Create custom tab bar:

import { View, Text, TouchableOpacity } from 'react-native';

function CustomTabBar({ state, descriptors, navigation }: any) { return ( <View style={{ flexDirection: 'row', height: 60 }}> {state.routes.map((route: any, index: number) => { const { options } = descriptors[route.key]; const isFocused = state.index === index;

    const onPress = () => {
      const event = navigation.emit({
        type: 'tabPress',
        target: route.key,
        canPreventDefault: true,
      });

      if (!isFocused &#x26;&#x26; !event.defaultPrevented) {
        navigation.navigate(route.name);
      }
    };

    return (
      &#x3C;TouchableOpacity
        key={route.key}
        onPress={onPress}
        style={{
          flex: 1,
          justifyContent: 'center',
          alignItems: 'center',
          backgroundColor: isFocused ? '#007AFF' : '#fff',
        }}
      >
        &#x3C;Text style={{ color: isFocused ? '#fff' : '#000' }}>
          {options.title || route.name}
        &#x3C;/Text>
      &#x3C;/TouchableOpacity>
    );
  })}
&#x3C;/View>

); }

<Tab.Navigator tabBar={(props) => <CustomTabBar {...props} />}> <Tab.Screen name="Home" component={HomeScreen} /> <Tab.Screen name="Profile" component={ProfileScreen} /> </Tab.Navigator>

Anti-Patterns

Don't Navigate in useEffect Without Dependencies

// Bad - Infinite loop risk useEffect(() => { navigation.navigate('Home'); });

// Good - Proper dependencies useEffect(() => { if (shouldNavigate) { navigation.navigate('Home'); } }, [shouldNavigate, navigation]);

Don't Use navigate() for Replacing Screens

// Bad - Adds to navigation stack navigation.navigate('SignIn');

// Good - Replaces current screen navigation.replace('SignIn');

Don't Access Navigation Without Type Safety

// Bad - No type safety function MyScreen({ navigation }: any) { navigation.navigate('Detials', { itemId: 123 }); // Typo won't be caught }

// Good - Type-safe navigation type Props = NativeStackScreenProps<RootStackParamList, 'Home'>;

function MyScreen({ navigation }: Props) { navigation.navigate('Details', { itemId: '123' }); // Type-checked }

Don't Forget to Handle Back Button on Android

import { useEffect } from 'react'; import { BackHandler } from 'react-native';

function MyScreen({ navigation }: any) { useEffect(() => { const backHandler = BackHandler.addEventListener( 'hardwareBackPress', () => { navigation.goBack(); return true; // Prevent default behavior } );

return () => backHandler.remove();

}, [navigation]);

return <View />; }

Related Skills

  • react-native-components: Building UI components for screens

  • react-native-platform: Platform-specific navigation behavior

  • react-native-performance: Optimizing navigation performance

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

android-jetpack-compose

No summary provided by upstream source.

Repository SourceNeeds Review
General

fastapi-async-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

storybook-story-writing

No summary provided by upstream source.

Repository SourceNeeds Review
General

atomic-design-fundamentals

No summary provided by upstream source.

Repository SourceNeeds Review