Reputation: 683
[I keep getting the error that says 'string' is not assignable to parameter of type 'never' in react native typescript and I don't know why. Can someone help me fix this bug.
Thank you in advance.
code snippet :
const loadReport = (id: string) => {
setPostId(id);
navigation.navigate('Report', {postId: id});
}
I get an underline under 'Report'.
Upvotes: 68
Views: 55943
Reputation: 1
The easiest way is, to install types/react-navigation by executing
npm i @types/react-navigation
and then in your code type const navigation = useNavigation<any>();
That's how I fixed it!
Upvotes: -2
Reputation: 9875
Maybe would be underrated but my solution was simpler, I notified my team about the issue and:
// @ts-ignore
navigation.navigate('WHERE_TF_I_WANT');
Upvotes: 0
Reputation: 453
Both solutions below work for me
const navigation = useNavigation<StackNavigationProp<any>>();
or
const navigation = useNavigation<any>();
Upvotes: 2
Reputation: 1
import { NavigationContext } from "@react-navigation/native";
const MyComponent = () => {
const navigation = React.useContext(NavigationContext);
...
}
Try this
Upvotes: 0
Reputation: 439
this is the correct solution of the typing you are searching for.
import React from 'react';
import {Text, View, Button} from 'react-native';
import {StackNavigationProp} from '@react-navigation/stack';
import {ParamListBase, useNavigation} from '@react-navigation/native';
enum Url {
Page1Screen = 'Page1Screen',
Page2Screen = 'Page2Screen',
Page3Screen = 'Page3Screen',
}
export const Page2Screen = () => {
const navigation = useNavigation<StackNavigationProp<ParamListBase, Url>>();
return (
<View>
<Text>page2</Text>
<Button
title="go to page 1"
onPress={() => navigation.navigate('Page1Screen')}
/>
<Button
title="go to page 3"
onPress={() => navigation.navigate('Page3Screen')}
/>
</View>
);
};
Upvotes: 2
Reputation: 61
I found this solution:
const route = ["path", { data }];
navigation?.navigate(...(route as never));
Upvotes: 1
Reputation: 1211
This is a weird issue that happens in RN > 0.65. My solution:
1.- Import:
{/* Depends of your Package (Stack or NativeStack...) */}
import { StackNavigationProp } from '@react-navigation/stack';
import { useNavigation } from '@react-navigation/core';
2.- Define types
export type RootStackParamList = {
YourScreen: { id: number } | undefined;
};
3.- Assign useNavigation hook with type StackNavigationProp.
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>();
4.- Use it! (Eye: with this type you can access to navigation object)
<TouchableOpacity
// Use this when you pass a parameter (is optional)
onPress={() => navigation.navigate('YourScreen', {id: 5})}>
</TouchableOpacity>
5.- Remember this notes:
Specifying undefined means that the route doesn't have params. A union type with undefined => AnyType | undefined means that params are optional.
The useNavigation const have special type and this final type takes 3 generics:
The param list object => RootStackParamList
The name of the screen route => RouteName
The ID of the navigator (optional) => NavigatorID
Obtained from: https://reactnavigation.org/docs/typescript/#annotating-usenavigation
Upvotes: 110
Reputation: 1078
I ran into this problem as well; in my case I was starting from the Ignite boilerplate. I solved it by using:
const navigation = useNavigation<NativeStackNavigationProp<AppStackParamList>>()
Where, in my case, AppStackParamList
is defined in app/navigators/AppNavigator.tsx
. There can be more than one Navigator and more than one ...StackParamList
; you'll wanna use the proper param list for the navigator your component is in. By passing the param list (instead of any
) to NativeStackNavigationProp
the type system can infer the list of route names for suggesting in navigation.navigate()
as well as other things relevant to your actual screen list.
Upvotes: 3
Reputation: 2048
Just use type any
when calling the hook:
const navigation = useNavigation<any>();
This isn't the recommended way of doing things but it will make the code error go away.
Upvotes: 13
Reputation: 153
You could make a maintainable navigation prop.
// navigation.ts
import { DrawerNavigationProp } from "@react-navigation/drawer";
import { NavigationProp } from "@react-navigation/native";
import { StackNavigationProp } from "@react-navigation/stack";
type RootStackParamList = {
// Your custom param type belongs here.
Login: {
id: string;
},
Profile: {},
}
type RootDrawerParamList = {
Shopping: {},
Chat: {},
}
export type RootNavigationProp = NavigationProp<
StackNavigationProp<RootStackParamList>,
DrawerNavigationProp<RootDrawerParamList>
>;
import { useNavigation } from "@react-navigation/native";
import { RootNavigationProp } from "@somewhere/navigation";
const App = () => {
const navigation = useNavigation<RootNavigationProp>();
function onPress () {
navigation.navigate("Login", {id: "userID"});
}
}
Upvotes: 3
Reputation: 695
Simple solution is to add any to NativeStackNavigationProp type
const AppLink = ({
text,
screenName,
}: Link) => {
// pass any to overload
const navigation = useNavigation<NativeStackNavigationProp<any>>();
const handleNavigation = () => {
navigation.navigate(screenName);
};
return (
<TouchableOpacity onPress={handleNavigation}>
<Text>{text}</Text>
</TouchableOpacity>
);
};
export default AppLink;
Upvotes: 25
Reputation: 3177
I too was getting the following ts error when not annotating useNavigation
and trying to call navigation.navigate('OtherJazzyScreen
)`:
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; }'
The OP doesn't specify which version of react-navigation they're using but you can fix this globally in React Navigation 6 which means you then don't have to annotate useNavigation
directly but you still get autocomplete and type checking.
Taken from the react-navigation blog in August 2021 (https://reactnavigation.org/blog/2021/08/14/react-navigation-6.0/#better-type-safety):
In React Navigation 6, you don’t need to annotate
useNavigation
to get autocompletion and type checking. This is possible by defining a type for the screens globally using declaration merging:declare global { namespace ReactNavigation { interface RootParamList { Home: undefined; Profile: { userId: string }; NotFound: undefined; } } }
You can read more about it in our TypeScript docs.
Another example from the React Navigation 6 docs, if you already have your params declared elsewhere:
// E.g. RootStackParamList.ts
export type RootStackParamList = {
Home: undefined;
Profile: { userId: string };
NotFound: undefined;
};
// E.g. App.tsx
import { RootStackParamList } from 'path/to/RootStackParamList';
declare global {
namespace ReactNavigation {
interface RootParamList extends RootStackParamList {}
}
}
Upvotes: 13
Reputation: 877
The only solution I found is to apply the type never on the string name.
const goToContent = () => {
navigate("Content" as never, {} as never);
};
I'm not sure it's the best solution but it's work.
Upvotes: 55