React Native Stack Navigator 不接受屏幕作为组件道具中的道具

React Native Stack Navigator does not accepts a Screen as a prop in component prop

我正在为这个 React Native 项目使用 expo v4.9.1。 我正在按照这个 Document 实现堆栈导航器。它是这样的 App.js

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Provider } from 'react-redux'
import HomeScreen from './screens/HomeScreen';
import { store } from './store';
import { SafeAreaProvider } from 'react-native-safe-area-context'
import 'react-native-gesture-handler';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import MapScreen from './screens/MapScreen';
import 'react-native-gesture-handler';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
import { GOOGLE_MAPS_APIKEY } from '@env'

export default function App() {

  const Stack = createStackNavigator();

  return (
    <Provider store={store}>
      <NavigationContainer>
        <SafeAreaProvider>
          <Stack.Navigator>
            <Stack.Screen name='HomeScreen' component={HomeScreen} options={{headerShown: false}}/>
            <Stack.Screen name='MapScreen' component={MapScreen} options={{headerShown: false}}/>
            <GooglePlacesAutocomplete 
              placeholder='Where From?'
              nearbyPlacesAPI='GooglePlacesSearch'
              debounce={300}
            />
          </Stack.Navigator>
        </SafeAreaProvider>
      </NavigationContainer>    
    </Provider>
    
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

HomeScreen 访问 MapScreen HomeScreen.js

import React from 'react'
import { StyleSheet, Text, View, SafeAreaView, Image } from 'react-native'
import tw from 'tailwind-react-native-classnames'
import NavOptions from '../components/NavOptions'

const HomeScreen = () => {
    return (
        <SafeAreaView style={tw`bg-white h-full`}>
            <View style={tw`p-5`}>
                <Image 
                    style={{
                        width: 100, 
                        height:100, 
                        resizeMode: 'contain',
                    }}
                    source={{
                        uri: 'https://links.papareact.com/gzs'
                    }}
                />

                <NavOptions />
            </View>
        </SafeAreaView>
    )
}

export default HomeScreen

const styles = StyleSheet.create({
    text: {
        color: 'blue',
    }
})

NavOptions.js

import { useNavigation } from '@react-navigation/native';
import React from 'react'
import { FlatList, Image, Text, TouchableOpacity, View } from 'react-native'
import { Icon } from 'react-native-elements/dist/icons/Icon';
import tw from 'tailwind-react-native-classnames'

const data =[
    {
        id: '123',
        title: 'Get a ride',
        image: 'https://links.papareact.com/3pn',
        screen: 'MapScreen',
    },
    {
        id: '456',
        title: 'Order food',
        image: 'https://links.papareact.com/28w',
        screen: 'EatScreen',
    }
];

const NavOptions = () => {

    const navigation = useNavigation();

    return (
        <FlatList 
            data={data}
            horizontal
            keyExtractor={(item) => item.id}
            renderItem={({ item }) => (
                <TouchableOpacity
                    onPress={() => navigation.navigate(item.screen)}
                    style={tw`p-2 pl-6 pb-8 pt-4 bg-gray-200 m-2 w-40 rounded-xl`}
                >
                    <View>
                        <Image 
                            style={{ width: 120, height: 120, resizeMode: 'contain' }}
                            source={{uri: item.image}}
                        />
                        <Text style={tw`mt-2 text-lg font-semibold`}>{item.title}</Text>
                        <Icon 
                            style={tw`p-2 bg-black rounded-full w-10 mt-4`}
                            type='antdesign'
                            name='arrowright'
                            color='white'
                        />
                    </View>
                </TouchableOpacity>

            )}
        />
    )
}

export default NavOptions

我用过useNavigation()钩子。但是我收到错误

A navigator can only contain 'Screen' components as its direct children (found 'undefined'). To render this component in the navigator, pass it in the 'component' prop to 'Screen'.

This error is located at:
    in StackNavigator (at App.js:23)
    in RNCSafeAreaProvider (at SafeAreaContext.tsx:76)
    in SafeAreaProvider (at App.js:22)
    in EnsureSingleNavigator (at BaseNavigationContainer.tsx:409)
    in ForwardRef(BaseNavigationContainer) (at NavigationContainer.tsx:91)
    in ThemeProvider (at NavigationContainer.tsx:90)
    in ForwardRef(NavigationContainer) (at App.js:21)
    in Provider (at App.js:20)
    in App (created by ExpoRoot)
    in ExpoRoot (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)
    in AppContainer (at renderApplication.js:39)
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:104:6 in reportException
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:171:19 in handleException
at node_modules/react-native/Libraries/Core/setUpErrorHandling.js:24:6 in handleError
at node_modules/expo-error-recovery/build/ErrorRecovery.fx.js:12:21 in ErrorUtils.setGlobalHandler$argument_0
at [native code]:null in flushedQueue
at [native code]:null in invokeCallbackAndReturnFlushedQueue

针对 Whosebug thread and GitHub issues thread 中完全相同的问题提供了一些解决方案。 None 其中对我有用,似乎没有关于此错误如何发生的确切解释。我也在使用 node v14.16.0npm v7.20.1

所以我深入研究了 react-navigation 的源代码并为您找到了答案。根据 https://github.com/react-navigation/react-navigation/blob/42a875212c5071b12e92eaf159ef488365413ab8/packages/core/src/useNavigationBuilder.tsx <Stack.Navigator> 的设计使其 children 仅为 Screen 个元素:

if (React.isValidElement(child)) {
  if (child.type === Screen) {
    // We can only extract the config from `Screen` elements
    // If something else was rendered, it's probably a bug
    acc.push([...

这就是为什么将 <GooglePlacesAutocomplete> 放在 <Stack.Navigator> 中你得到了一个错误

throw new Error(
  `A navigator can only contain 'Screen' as its direct children ...
);