2

I am using expo v4.9.1 for this react native project. I am implementing the stack navigator as per this Document. It goes this way 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',
  },
});

the MapScreen is accessed from HomeScreen 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

I have used useNavigation() hook. Yet I am getting the error

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

There are some solutions provided for THE EXACT SAME PROBLEM IN StackOverflow thread and GitHub issues thread. None of them work for me and there seem to be no exact explanation as to how this error occurs. Also I am using node v14.16.0 and npm v7.20.1

Vaibhav07
  • 223
  • 2
  • 10
  • 1
    How your MapScreen looks like? Does removing makes any difference? – ishaba Jul 31 '21 at 06:43
  • Map Screen is empty just initialized and exported it. I removed , It worked! but how could this affect stack navigator? – Vaibhav07 Jul 31 '21 at 07:03
  • 2
    Thats how is designed for some reason it's children must be only components – ishaba Jul 31 '21 at 07:11
  • 1
    The error message says exactly what is wrong here. Stack.Navigator can only contain Screen components as it's direct child. Right now you have two Screen components and one GooglePlacesAutoComplete component as direct child. Put the GoogleAutoComplete component in one of your Screen components instead. – Qw4z1 Jul 31 '21 at 11:44

1 Answers1

3

So i dived a bit into the source code of react-navigation and found an answer for you. According to https://github.com/react-navigation/react-navigation/blob/42a875212c5071b12e92eaf159ef488365413ab8/packages/core/src/useNavigationBuilder.tsx <Stack.Navigator> is designed to have its children to be only Screen elements:

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([...

Thats why placing the <GooglePlacesAutocomplete> inside <Stack.Navigator> you got en error

throw new Error(
  `A navigator can only contain 'Screen' as its direct children ...
);
ishaba
  • 551
  • 2
  • 10