0

I'm coming from ReactJS and a bit confused about how to navigate between screens in react native.

I'm using these react-navigation and react-navigation-stack versions:

"@react-navigation/native": "^5.8.10", "@react-navigation/stack": "^5.12.8"

So I have 2 screens already:

SplashScreenContainer

import React from 'react';
import {Text, View} from "react-native-reanimated";

class SplashScreenContainer extends React.PureComponent {

    redirectToHome  = () => {
        const {navigation} = this.props;
        navigation.navigate('HomeContainer');
    }

    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text onPress={() => this.redirectToHome}>
                    Splash Screen
                </Text>
            </View>
        )
    }
}

export default SplashScreenContainer;

HomeScreenContainer

import React from 'react';
import {Text, View} from "react-native-reanimated";

class HomeScreenContainer extends React.PureComponent {
    render() {
        return (
            <View>
                <Text>Home Screen</Text>
            </View>
        )
    }
}

export default HomeScreenContainer;

and here's my app js to render the screens inside NavigationContainer:

App.js

import React from 'react';
import {SafeAreaView} from "react-native-safe-area-context";
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';

const SplashScreenContainer = React.lazy(() => import('./app/containers/SplashScreenContainer'));
const HomeContainer = React.lazy(() => import('./app/containers/HomeContainer'));

const Stack = createStackNavigator();

class App extends React.PureComponent {
    render() {
        return (
            <SafeAreaView>
                <NavigationContainer>
                    <Stack.Navigatior>
                        <Stack.Screen name='SplashScreenContainer' component={() => <SplashScreenContainer {...this.props} />}/>
                        <Stack.Screen name='HomeContainer' component={() => <HomeContainer {...this.props} />}/>
                    </Stack.Navigatior>
                </NavigationContainer>
            </SafeAreaView>
        )
    }
}

export default App;

After I run with npm run ios command, the console gives me this error:

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

I don't understand what is this error about, what am I missing here? how can I navigate between the screens in react-native?

Any help will be much appreciated. Thank You.

Regards

M Ansyori
  • 429
  • 6
  • 21
  • Read the doc here https://reactnavigation.org/docs/navigating this will help you how to move between screens. By the way Text do not have onPress prop, you should use a Button or Touchables to capture user interaction – Sameer Kumar Jain Dec 05 '20 at 18:22
  • lazy={true} (depending on your navigation npm version) https://stackoverflow.com/questions/47890571/difference-between-lazyload-and-lazy-in-react-navigation-options – Eran Dec 05 '20 at 19:21
  • @Eran I changed React.lazy into import but still getting the same error message – M Ansyori Dec 05 '20 at 19:30
  • 1
    Might be something with Stack.screen rendering : https://stackoverflow.com/a/61262356/205477 i'll try that – Eran Dec 05 '20 at 20:01
  • @Eran thanks, you're correct. There's something is wrong with the stack screen so I make a couple of changes. thanks for the hint. – M Ansyori Dec 06 '20 at 03:58

1 Answers1

1

Well, I made it works. Here are the changes I made:

  1. Remove SafeAreaView from App.js
  2. Add {Suspense} in App.js because I forgot that React.lazy depends on Suspense
  3. Use SafeAreaView in Home and SplashScreen imported from 'react-native'

App.js

import React, {Suspense} from 'react';
import {SafeAreaView, Text} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';

const SplashScreenContainer = React.lazy(() => import('./app/containers/SplashScreenContainer'));
const HomeContainer = React.lazy(() => import('./app/containers/HomeContainer'));

const Stack = createStackNavigator();

const Loading = () => {
    return (
        <SafeAreaView>
            <Text>Loading</Text>
        </SafeAreaView>
    )
};

const Routes = () => {
    return (
        <NavigationContainer>
            <Stack.Navigator initialRouteName='SplashScreenContainer'>
                <Stack.Screen
                    name='SplashScreenContainer'
                    component={SplashScreenContainer}
                    options={{ headerShown: false }}
                />
                <Stack.Screen
                    name='HomeContainer'
                    component={HomeContainer}
                    options={{ headerShown: false }}
                />
            </Stack.Navigator>
        </NavigationContainer>
    )
}

class App extends React.PureComponent {
    render() {
        return (
            <Suspense fallback={<Loading/>}>
                <Routes/>
            </Suspense>
        )
    }
}

export default App;

SplashScreenContainer.js

import React from 'react';
import {Button, SafeAreaView} from 'react-native';

class SplashScreenContainer extends React.PureComponent {

    constructor(props) {
        super(props);
    }

    redirectToHome = () => {
        const {navigation} = this.props;
        navigation.navigate('HomeContainer');
    };

    render() {
        return (
            <SafeAreaView style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Button onPress={() => this.redirectToHome()} title='Go To Home Screen'/>
            </SafeAreaView>
        )
    }

}

export default SplashScreenContainer;

HomeScreenContainer.js

import React from 'react';
import {Button, SafeAreaView} from 'react-native';

class HomeContainer extends React.PureComponent {

    redirectToSplash = () => {
        const {navigation} = this.props;
        navigation.navigate('SplashScreenContainer');
    };

    render() {
        return (
            <SafeAreaView style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Button onPress={() => this.redirectToSplash()} title='Go To Splash Screen'/>
            </SafeAreaView>
        )
    }

}

export default HomeContainer;

Everything's working now, I'm able to switch between SplashScreen and HomeScreen when button is clicked/tapped.

M Ansyori
  • 429
  • 6
  • 21