“React Native bottom tab navigator element is not assignable.”

huangapple go评论56阅读模式
英文:

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&lt;RootTabParamList&gt; | undefined;
   	Modal: undefined;
    NotFound: undefined;
};

export type RootStackScreenProps&lt;Screen extends keyof RootStackParamList&gt; = NativeStackScreenProps&lt;
    RootStackParamList,
	Screen
&gt;;
    
const BottomTab = createBottomTabNavigator&lt;RootTabParamList&gt;();
    
type RootTabParamList = {
    About: undefined;
   	Test: undefined;
};
    
export type RootTabScreenProps&lt;Screen extends keyof RootTabParamList&gt; = CompositeScreenProps&lt;
   	BottomTabScreenProps&lt;RootTabParamList, Screen&gt;,
   	NativeStackScreenProps&lt;RootStackParamList&gt;
&gt;;
   
export default function Navigation({ colorScheme }: { colorScheme: ColorSchemeName }) {
   	return (
    	&lt;NavigationContainer
	    	linking={LinkingConfiguration}
		    theme={colorScheme === &#39;dark&#39; ? DarkTheme : DefaultTheme}
   		&gt;
    		&lt;Stack.Navigator&gt;
	    		&lt;Stack.Screen name=&quot;Tabs&quot; component={BottomTabNavigator} options={{ headerShown: false }}/&gt;
		    	// (!) Problem line
		    	&lt;Stack.Screen name=&quot;NotFound&quot; component={NotFoundScreen} options={{ title: &#39;Oops!&#39; }}/&gt;
			    &lt;Stack.Group screenOptions={{ presentation: &#39;modal&#39; }}&gt;
				    &lt;Stack.Screen name=&quot;Modal&quot; component={ModalScreen} /&gt;
   				&lt;/Stack.Group&gt;
    		&lt;/Stack.Navigator&gt;
	    &lt;/NavigationContainer&gt;
	);
}

I found out which is the right type for the {navigation} in one of the tabs, e.g. About.tsx:

import React from &#39;react&#39;;
import { StyleSheet, TouchableOpacity } from &#39;react-native&#39;;

import { Text, View } from &#39;../ui/Components&#39;;
import { RootTabScreenProps } from &#39;../ui/Navigation&#39;;

export default function About({ navigation }: RootTabScreenProps&lt;&#39;About&#39;&gt;) {
  return (
    &lt;View style={styles.container}&gt;
      &lt;Text style={styles.title}&gt;About&lt;/Text&gt;
      &lt;View style={styles.separator} lightColor=&quot;#eee&quot; darkColor=&quot;rgba(255,255,255,0.1)&quot; /&gt;
      &lt;Text&gt;/screens/About.tsx&lt;/Text&gt;
      &lt;TouchableOpacity onPress={() =&gt; navigation.replace(&#39;Tabs&#39;)}&gt;
        &lt;Text&gt;Go to home screen!&lt;/Text&gt;
      &lt;/TouchableOpacity&gt;
    &lt;/View&gt;
  );
}

But I can't find the right type for the {navigation} in the root components (no tabs), like NotFound.tsx:

import React from &#39;react&#39;;
import { StyleSheet, TouchableOpacity } from &#39;react-native&#39;;

import { Text, View } from &#39;../ui/Components&#39;;

// (!) Problem line
export default function NotFoundScreen({ navigation }: ?????) {
  return (
    &lt;View style={styles.container}&gt;
      &lt;Text style={styles.title}&gt;This screen doesn&#39;t exist.&lt;/Text&gt;
      &lt;TouchableOpacity onPress={() =&gt; navigation.replace(&#39;Tabs&#39;)} style={styles.link}&gt;
        &lt;Text style={styles.linkText}&gt;Go to home screen!&lt;/Text&gt;
      &lt;/TouchableOpacity&gt;
    &lt;/View&gt;
  );
}

Without the type, I (of course) get an error in NotFound.tsx, that
> Binding element 'navigation' implicitly has an 'any' type.

I tried RootStackScreenProps&lt;&#39;NotFound&#39;&gt;, which will let the error above disappear, but instead I get an error in Navigation.tsx on line &lt;Stack.Screen name=&quot;NotFound&quot; component={NotFoundScreen} options={{ title: &#39;Oops!&#39; }}/&gt;:
>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 &#39;react&#39;;
import { StyleSheet, TouchableOpacity } from &#39;react-native&#39;;
import { RootStackParamList } from &#39;../ui/Navigation&#39;;
import { NativeStackScreenProps } from &#39;@react-navigation/native-stack&#39;;
import { Text, View } from &#39;../ui/Components&#39;;

type Props = NativeStackScreenProps&lt;RootStackParamList&gt;; // don&#39;t use &lt;Screen&gt; here

export default function NotFoundScreen({ navigation }: Props) {
  return (
    &lt;View style={styles.container}&gt;
      &lt;Text style={styles.title}&gt;This screen doesn&#39;t exist.&lt;/Text&gt;
      &lt;TouchableOpacity onPress={() =&gt; navigation.replace(&#39;Tabs&#39;)} style={styles.link}&gt;
        &lt;Text style={styles.linkText}&gt;Go to home screen!&lt;/Text&gt;
      &lt;/TouchableOpacity&gt;
    &lt;/View&gt;
  );
}

答案2

得分: 0

感谢 @phantomspooks 的帮助和他的回答(https://stackoverflow.com/a/76248413/4090157),我现在对类型有了更好的理解。

最终,我通过进行以下更改成功解决了我的问题:

  1. Navigation.tsx 中从 export type RootStackScreenProps 中删除 &lt;Screen&gt;
export type RootStackScreenProps = NativeStackScreenProps&lt;
    RootStackParamList
&gt;;
  1. 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:

  1. Remove &lt;Screen&gt; from export type RootStackScreenProps in Navigation.tsx
export type RootStackScreenProps = NativeStackScreenProps&lt;
	RootStackParamList
&gt;;
  1. Use that type in NotFound.tsx
export default function NotFoundScreen({ navigation }: RootStackScreenProps) {
    ...
}

huangapple
  • 本文由 发表于 2023年5月14日 22:35:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76248020.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定