Anthony Davi
Anthony Davi

Reputation: 1

React Native Navigation Argument of type 'string' is not assignable to parameter of type

I have this problem with react native, react navigation, even with this error the navigation flow is still working.

Argument of type 'string' is not assignable to parameter of type '{ key: string; params?: undefined; merge?: boolean | undefined; } | { name: never; key?: string | undefined; params: never; merge?: boolean | undefined; }'.ts(2345)

export function LoginContainer() {
    const navigation = useNavigation()
    async function handleSignInEmail() {
        navigation.navigate('SingInEmail')
    }

    return (
        <Container>
                <Image source={Logo} />
                <Title>Você está entrando com uma conta de Cliente.</Title>
                <LoginButton
                    title="Entrar com Google"
                    type="google"
                />
                <LoginButton
                    title="Entrar com Facebook"
                    type="facebook"
                />
                <Divisor/>
                <Links
                    title="Entrar com Email"
                    onPress={handleSignInEmail}
                />
                <Links
                    title="Cadastrar-se"
                />
        </Container>
    )
}

The error occurs in navigation.navigate('SingInEmail')

My package.json

{
  "name": "smart-delivery",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "android": "expo run:android",
    "ios": "expo run:ios",
    "web": "expo start --web",
    "start": "react-native start"
  },
  "dependencies": {
    "@expo-google-fonts/josefin-sans": "^0.2.0",
    "@expo-google-fonts/ubuntu": "^0.2.0",
    "@react-navigation/native": "^5.9.4",
    "@react-navigation/stack": "^5.14.5",
    "expo": "~43.0.2",
    "expo-app-loading": "~1.2.1",
    "expo-font": "~10.0.3",
    "expo-splash-screen": "~0.13.5",
    "expo-status-bar": "~1.1.0",
    "expo-updates": "~0.10.13",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "react-native": "0.64.3",
    "react-native-gesture-handler": "~1.10.2",
    "react-native-iphone-x-helper": "^1.3.1",
    "react-native-reanimated": "~2.2.0",
    "react-native-responsive-fontsize": "^0.5.1",
    "react-native-safe-area-context": "3.3.2",
    "react-native-screens": "~3.8.0",
    "react-native-svg": "12.1.1",
    "react-native-web": "0.17.1",
    "styled-components": "^5.3.3"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@types/react": "~17.0.21",
    "@types/react-native": "~0.64.12",
    "@types/styled-components-react-native": "^5.1.3",
    "typescript": "~4.3.5"
  },
  "private": true
}

I believe the error is in the typescript, I'm using this template.

My routes are all centered in an index.tsx, here it is.

const { Navigator, Screen } = createNativeStackNavigator();

export function Routes() {
    return (
        <NavigationContainer>
            <Navigator
                screenOptions={{
                    headerShown: false
                }}
            >
                <Screen
                    name="AccessType"
                    component={AccessType}
                />
                <Screen
                    name="SignIn"
                    component={SignIn}
                />
            </Navigator>
        </NavigationContainer>
    )
}

Upvotes: 0

Views: 5178

Answers (4)

Timcu Alexei
Timcu Alexei

Reputation: 290

You have to provide type checking for react-navigation . About this you can read here.

type RootStackParamList = {
  Home: undefined;
  SingInEmail: undefined;
};

...

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

const RootStack = createStackNavigator<RootStackParamList>();

After this instead of manually annotating these APIs, you can specify a global type for your root navigator which will be used as the default type.

To do this, you can add this snippet somewhere in your codebase:

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

Upvotes: 0

ranu
ranu

Reputation: 652

The problem here is that when you are using typescript the IntelliSense comes into play and it warns you about the incorrect type usage. You see, the definition of the navigate function is defined as follows:

navigate<RouteName extends keyof ParamList>(options: {
    key: string;
    params?: ParamList[RouteName];
    merge?: boolean;
} | {
    name: RouteName;
    key?: string;
    params: ParamList[RouteName];
    merge?: boolean;
}): void;

It expects an object with two possible forms. The first form inforces you to define an object such as o = {key: 'some key'}, the other two object keys are optional as specified in the documentation (observe the definition of the params and the merge).

The second form expects an object defined as o = {'name': '<route-name>', ...} and this is the one you are looking for. Although params is not optional in this form you don't need to specify it in this case and you'll have to define the key in this case (and I have no idea why as it is defined as optional).

In summary, you could use the following function and IntelliSense will be happy.

function to(page: string): void {
  let m = {
      name: page,
      key: '',
  }
  navigation.navigate(m);
}

Upvotes: 0

Hugo Campos
Hugo Campos

Reputation: 1

Yes, you are trying to navigate to "SignInEmail" instead of "SignIn"

Upvotes: 0

Kypps
Kypps

Reputation: 346

I suppose your problem is that you're trying to navigate to a route which is not in the router/navigation container.

When calling navigation.navigate('SingInEmail'), your component is SingInEmail, which is not in a screen.

I suppose you meant to write navigation.navigate('SignIn') which is a Screen and so, the navigate returns to the component SignIn.

Upvotes: 0

Related Questions