29

When I use useNavigation or from props { navigation } for navigate between screen using navigation.navigate('Home') the typescript return error Argument of type '"Main"' is not assignable to parameter of type '{ key: string; params?: undefined; merge?: boolean | undefined; } | { name: never; key?: string | undefined; params: never; merge?: boolean | undefined; }' what does it mean?

below is my code:

import React from 'react';
import { View } from 'react-native';
import { Button } from 'react-native-paper';
import { useNavigation } from '@react-navigation/native';

const Home: React.FC = () => {
  const navigation = useNavigation();

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Button onPress={() => navigation.navigate('Main')}>Navigate</Button>
    </View>
  );
};

export default React.memo(Home);

previously i used react navigation v5 and working find with that method

thanks for your help

Pierre Said
  • 3,660
  • 1
  • 16
  • 28
Umar Alfaruq
  • 507
  • 1
  • 6
  • 8
  • `navigation.navigate({...params})` – Pim Aug 14 '21 at 06:23
  • Take a look Specifying default types for useNavigation, Link, ref etc at: https://reactnavigation.org/docs/typescript/#specifying-default-types-for-usenavigation-link-ref-etc – jessmzn Nov 27 '21 at 16:37
  • This [example from react-navigation documentation](https://reactnavigation.org/docs/typescript/) helped me understand what types are needed. – Cezar Cobuz Aug 15 '22 at 03:42

7 Answers7

45

Maybe you want to do something like this:

export type RootStackParamList = {
  Main: undefined;
  Home: undefined;
};

const Stack = createStackNavigator<RootStackParamList>();

export const RootNavigator = () => {
  return (
    <Stack.Navigator initialRouteName="Main">
      <Stack.Screen
        name="Main"
        component={Main}
      />
      <Stack.Screen
        name="Home"
        component={Home}
      />
    </Stack.Navigator>
  );
};

then in your code to do something like this:

type homeScreenProp = StackNavigationProp<RootStackParamList, 'Home'>;

const Home: React.FC = () => {
  const navigation = useNavigation<homeScreenProp>();

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Button onPress={() => navigation.navigate('Main')}>Navigate</Button>
    </View>
  );
};
Pierre Said
  • 3,660
  • 1
  • 16
  • 28
Asiel Alonso
  • 561
  • 4
  • 6
18

This is because you must specify this type, as this will ensure type-safety.

Solution:

1 - Type checking the navigator

// root.routes.tsx

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

export type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
  Feed: { sort: 'latest' | 'top' } | undefined;
};
const RootStack = createStackNavigator<RootStackParamList>();

2 - Specify a global type for your root navigator

// navigation.d.ts

import { RootStackParamList } from '../routes/root.routes';

declare global {
  namespace ReactNavigation {
    interface RootParamList extends RootStackParamList { }
  }
}

3 - Use it!

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

const navigation = useNavigation();

navigation.navigate('Home');

4- Extra! If you need to grab a parameter:

import { useRoute, RouteProp } from '@react-navigation/native';
import { RootStackParamList } from '../routes/root.routes';

const route = useRoute<RouteProp<RootStackParamList, 'Profile'>>();

const id = route.params.userId;

Refs:

Sanchitos
  • 8,423
  • 6
  • 52
  • 52
ambegossi
  • 181
  • 1
  • 3
  • I am facing errr in line const RootStack = createStackNavigator(); Parsing error: Unexpected token (81:56)eslint Expression expected.ts(1109) – Pintu Rajput Nov 30 '22 at 15:49
11

I solved this problem, it will help for now, but it's not the correct typing:

type Nav = {
  navigate: (value: string) => void;
}

const { navigate } = useNavigation<Nav>()

function foo() {
  navigate("Home")
}
Josué Mendonça
  • 460
  • 4
  • 11
6

While the other answers cover a good amount, I think I may add to this by describing usage in the useNavigation hook as well as passing the {navigation} through props to a screen.

First, setup the Stack Navigator:

/**
* Types for Stack Navigator.
*/
export type StackParamList = {
  Main: undefined;
  Home: undefined;
};

const Stack = createStackNavigator<StackParamList>();
  • When using the useNavigation hook:
import { StackNavigationProp } from "@react-navigation/stack";

/**
 * Types for the Stack Navigator.
 */
export type StackNavigation = StackNavigationProp<StackParamList>;

const navigation = useNavigation<StackNavigation>();
  • When passing the navigation down as a prop in a screen:
/**
 * Types for passing the navigation props to screens in the Bottom Tab Navigator.
*/
export type StackNavigationProps = {
  navigation: StackNavigation;
};

const SomeScreenInTheStack = ({ navigation }: StackNavigationProps) => {
...
}

Hope this is useful to someone!

Pierre Said
  • 3,660
  • 1
  • 16
  • 28
David Alford
  • 2,044
  • 3
  • 12
  • 35
0

I think the best way is this:

  1. create a file @types/index.ts inside this file paste de code:
  routeNames: never[];
};

export type navigationProps = {
  navigate: (screen?: string) => void;
  goBack: () => void;
  reset: (index: number, routeNames: Routes[]) => void;
};

  1. Now you just need to use the navigationProps as the generic of useNavigation example:
import { useNavigation } from '@react-navigation/native';

 const navigation = useNavigation<navigationProps>();

Rodrigo Dias
  • 114
  • 1
  • 9
0

Easy way for this is:

navigation.navigate('Main' as never)}

-2

You can just put a Type on the screen name. Just like:

const handleContinue = () => navigation.navigate('Login' as never);