英文:
React Native bottom tab navigator element is not assignable
问题
The correct type to use for the {navigation}
parameter in the NotFound.tsx
component is RootStackScreenProps<'NotFound'>
.
So your NotFound.tsx
component should look like this:
import React from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { Text, View } from '../ui/Components';
import { RootStackScreenProps } from '../ui/Navigation';
export default function NotFoundScreen({ navigation }: RootStackScreenProps<'NotFound'>) {
return (
<View style={styles.container}>
<Text style={styles.title}>This screen doesn't exist.</Text>
<TouchableOpacity onPress={() => navigation.replace('Tabs')} style={styles.link}>
<Text style={styles.linkText}>Go to home screen!</Text>
</TouchableOpacity>
</View>
);
}
This should resolve the type error in NotFound.tsx
.
英文:
I am new to React and TypeScript and I created an app with Expo Go that contains the React Bottom Tab Navigator (https://reactnavigation.org/docs/bottom-tab-navigator/). My problem is that the example does not define the types for the {navigation}
parameter and I would like to solve this.
Note: it works without defining the type, but I would like to learn and understand how to fix it...
I have a Navigation.tsx
containing my root stack and the tabs (I hope I limited it to the relevant parts)
const Stack = createNativeStackNavigator();
declare global {
namespace ReactNavigation {
interface RootParamList extends RootStackParamList { }
}
}
type RootStackParamList = {
Tabs: NavigatorScreenParams<RootTabParamList> | undefined;
Modal: undefined;
NotFound: undefined;
};
export type RootStackScreenProps<Screen extends keyof RootStackParamList> = NativeStackScreenProps<
RootStackParamList,
Screen
>;
const BottomTab = createBottomTabNavigator<RootTabParamList>();
type RootTabParamList = {
About: undefined;
Test: undefined;
};
export type RootTabScreenProps<Screen extends keyof RootTabParamList> = CompositeScreenProps<
BottomTabScreenProps<RootTabParamList, Screen>,
NativeStackScreenProps<RootStackParamList>
>;
export default function Navigation({ colorScheme }: { colorScheme: ColorSchemeName }) {
return (
<NavigationContainer
linking={LinkingConfiguration}
theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}
>
<Stack.Navigator>
<Stack.Screen name="Tabs" component={BottomTabNavigator} options={{ headerShown: false }}/>
// (!) Problem line
<Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }}/>
<Stack.Group screenOptions={{ presentation: 'modal' }}>
<Stack.Screen name="Modal" component={ModalScreen} />
</Stack.Group>
</Stack.Navigator>
</NavigationContainer>
);
}
I found out which is the right type for the {navigation}
in one of the tabs, e.g. About.tsx
:
import React from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { Text, View } from '../ui/Components';
import { RootTabScreenProps } from '../ui/Navigation';
export default function About({ navigation }: RootTabScreenProps<'About'>) {
return (
<View style={styles.container}>
<Text style={styles.title}>About</Text>
<View style={styles.separator} lightColor="#eee" darkColor="rgba(255,255,255,0.1)" />
<Text>/screens/About.tsx</Text>
<TouchableOpacity onPress={() => navigation.replace('Tabs')}>
<Text>Go to home screen!</Text>
</TouchableOpacity>
</View>
);
}
But I can't find the right type for the {navigation}
in the root components (no tabs), like NotFound.tsx
:
import React from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { Text, View } from '../ui/Components';
// (!) Problem line
export default function NotFoundScreen({ navigation }: ?????) {
return (
<View style={styles.container}>
<Text style={styles.title}>This screen doesn't exist.</Text>
<TouchableOpacity onPress={() => navigation.replace('Tabs')} style={styles.link}>
<Text style={styles.linkText}>Go to home screen!</Text>
</TouchableOpacity>
</View>
);
}
Without the type, I (of course) get an error in NotFound.tsx
, that
> Binding element 'navigation' implicitly has an 'any' type.
I tried RootStackScreenProps<'NotFound'>
, which will let the error above disappear, but instead I get an error in Navigation.tsx
on line <Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }}/>
:
>Type '({ navigation }: RootStackScreenProps<"NotFound">) => Element' is not assignable to type 'ScreenComponentType<ParamListBase, "NotFound"> | undefined'.<br/>
> Type '({ navigation }: RootStackScreenProps<"NotFound">) => Element' is not assignable to type 'FunctionComponent<{}>'.<br/>
> Types of parameters '__0' and 'props' are incompatible.<br/>
> Type '{}' is missing the following properties from type 'RootStackScreenProps<"NotFound">': navigation, route
So... What is the right type to use here?
答案1
得分: 1
React Navigation是使用TypeScript编写的,因此与它相关的任何类型可能都已存在。在这里,它们涵盖了如何为堆栈导航器进行类型检查,底部选项卡导航器的原理也相同。您只需在您的 NotFound.tsx
中导出 RootStackParamList
并导入 NativeStackScreenProps
:
import React from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { RootStackParamList } from '../ui/Navigation';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { Text, View } from '../ui/Components';
type Props = NativeStackScreenProps<RootStackParamList>; // 不要在这里使用 <Screen>
export default function NotFoundScreen({ navigation }: Props) {
return (
<View style={styles.container}>
<Text style={styles.title}>This screen doesn't exist.</Text>
<TouchableOpacity onPress={() => navigation.replace('Tabs')} style={styles.link}>
<Text style={styles.linkText}>Go to home screen!</Text>
</TouchableOpacity>
</View>
);
}
英文:
react navigation was written in typescript, so any type you would need relating to it probably exists. Here they cover typing a Stack Navigator, and its same premises for a bottom tab navigator. You just need to export RootStackParamList
and import NativeStackScreenProps
in your NotFound.tsx
:
import React from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { RootStackParamList } from '../ui/Navigation';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { Text, View } from '../ui/Components';
type Props = NativeStackScreenProps<RootStackParamList>; // don't use <Screen> here
export default function NotFoundScreen({ navigation }: Props) {
return (
<View style={styles.container}>
<Text style={styles.title}>This screen doesn't exist.</Text>
<TouchableOpacity onPress={() => navigation.replace('Tabs')} style={styles.link}>
<Text style={styles.linkText}>Go to home screen!</Text>
</TouchableOpacity>
</View>
);
}
答案2
得分: 0
感谢 @phantomspooks 的帮助和他的回答(https://stackoverflow.com/a/76248413/4090157),我现在对类型有了更好的理解。
最终,我通过进行以下更改成功解决了我的问题:
- 在
Navigation.tsx
中从export type RootStackScreenProps
中删除<Screen>
export type RootStackScreenProps = NativeStackScreenProps<
RootStackParamList
>;
- 在
NotFound.tsx
中使用该类型
export default function NotFoundScreen({ navigation }: RootStackScreenProps) {
...
}
英文:
Thanks to the help of @phantomspooks and his answer (https://stackoverflow.com/a/76248413/4090157), I think I now understand the types a bit better.
I was finally able to resolve my problem by making the following changes:
- Remove
<Screen>
fromexport type RootStackScreenProps
inNavigation.tsx
export type RootStackScreenProps = NativeStackScreenProps<
RootStackParamList
>;
- Use that type in
NotFound.tsx
export default function NotFoundScreen({ navigation }: RootStackScreenProps) {
...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论