I'm struggling to figure out why my code doesn't work. I keep reading the tutorials and nothing helps. How can I switch between screens and have the screens in different JS files (as components)?
Currently, my code works for the first screen, but when I click on the button nothing shows up.
Please see the codes below:
App.js
import * as React from 'react';
import {Button, View, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import TestScreen from './components/Test';
//HOME SCREEN
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Test"
onPress={() => navigation.navigate('Test',{myParam: '03',})}
/>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Test" component={TestScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Test.js
import React, { Component } from "react";
import { Text, View } from "react-native";
class Test extends Component {
render() {
const { navigation } = this.props;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Test Screen</Text>
<Button
title="Test"
onPress={() => navigation.navigate('Home')}
/>
</View>
);
}
}
export default Test;
It seems it was a very simple issue and I figured it out myself. The code in Test.js was missing 'Button' in the import statement. The correct way should be:
import { Button, Text, View } from "react-native";
It's a silly mistake, but it's not the first time this happens to me. I use Visual Studio Code, which highlights missing connections, but it seems that this doesn't work for some components. Not to mention it compiles (bundling) with no problems.
Nevertheless, the code works fine now.
First you have to import useNavigation in Test.js file.
Like this:
import { useNavigation } from "#react-navigation/core";
Then you have to use it and save it in a variable like:
const navigation = useNavigation();
Now use:
onPress={() => navigation.navigate('Home')};
This will navigate to the the other Screen.
Make sure you install every library you use in your project using npm or yarn.
Related
I started React Native couple of days ago. Trying to create basic native apps. When i try react native navigation 5 i am gettin this error. Couldn't find similiar problem with this version of it.
TypeError: route is undefined
My Code is:
import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import AppLogo from "./modules/AppLogo";
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
I have just started learning React Native. I am trying to insert bottom menu tabs on my first app.
I am using this code on Tabs.js (this is just the export part):
export default function Tabs() {
return (
<NavigationContainer>
<MyTabs />
</NavigationContainer>
);
}
Unfortunately, I don't know how to call it to my main App file (this is just one of my attempts):
import * as React from 'react';
import { Text, View } from 'react-native';
import Tabs from './Tabs.js';
Tabs();
I've read about exporting default function, but I don't understand how to use it in my main App file. I'm sure that this is a syntax issue.
Also, I am planning to add a background colour to all tabs. Any advice?
Thank you.
UPDATE:
This is my Tabs file.
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { MaterialCommunityIcons } from '#expo/vector-icons';
const Tabs = () => {
function Feed() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
function Profile() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
function MainPage() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator
initialRouteName="Feed"
tabBarOptions={{
activeTintColor: '#e91e63',
}}
>
<Tab.Screen
name="Feed"
component={Feed}
options={{
tabBarLabel: '',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="MainPage"
component={MainPage}
options={{
tabBarLabel: '',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="pill" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Profile"
component={Profile}
options={{
tabBarLabel: '',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="format-list-text" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
);
}
return (
<NavigationContainer>
<MyTabs />
</NavigationContainer>
);
}
export default Tabs
This is my main App file.
import * as React from 'react';
import { Text, View } from 'react-native';
import Tabs from './Tabs.js';
const App=()=>{
return <Tabs />
}
Make sure to export the App as default. You most probably have a file called index.js in the root folder and that is importing your App component.
Your App.js file should look like this:
import * as React from 'react';
import { Text, View } from 'react-native';
import Tabs from './Tabs.js';
export default const App=()=>{
return <Tabs />
}
And then your index.js file looks like this:
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
You don't necessarily have to export as default, because you can only have one default export. If you export App as default you import it like this: import App from './App'; and if you export without a default, you have to import like this: import {App} from './App'
And to get an advice how to add background color to the tabs, check here: How to set the background color of Tab.Navigator?
you basically call it like would call a component
btw your Tabs should export like this
const Tabs=()=>{
/...
}
export default Tabs
const App=()=>{
return <Tabs />
}
I'm using React Native Navigation dependency as route. But I have problem in the following code which appears to do nothing.
I'm trying to create 2 screens, one is login, the other is register (later on I will add button to move between them, right now even the default screen doesn't work).
App.JS
import React from 'react';
import { View, StatusBar, Text } from 'react-native';
import Login from './login.js';
export default function App() {
return (
<View>
<StatusBar barStyle="dark-content" hidden={false} backgroundColor="#ffffff" translucent={true}/>
<Login/>
</View>
);
}
Login.JS
import React from 'react';
import Register from './register.js';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
function LoginScreen() {
return (
<View style={{ flex: 1, paddingTop: 100, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
const Stack = createStackNavigator();
function Login() {
return (
<View style={styles.container}>
<Text style={styles.logo}>My Title</Text>
<Text style={styles.slogan}>Welcome</Text>
<NavigationContainer>
<Stack.Navigator initialRouteName="Login">
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Register" component={Register} />
</Stack.Navigator>
</NavigationContainer>
</View>
);
}
export default Login;
By reading the docs that should work, but I can't understand what is wrong here.
I receive blank area in the stack screen area.
I have tried to replace Register component with function, didn't work either.
How can I display React Native Navigation stack screen correctly?
How about having the Navigation Container wrap the contents of App.js then you can leave the Stack navigator and screens in the Login component
The container around your navigation has a background-color, so remove all background-color around it and see again.
I'm starting an app and I have two views at the moment, one called Splash and the other called Home. It happens that when the splash is over it leads me to the Home view, but in this view the user presses the button backwards, the app shows me the splash again. Is there a way to avoid this? the idea is that being in the Home view there is no way to roll back the application.
MainStackNavigator.js
import * as React from 'react'
import { NavigationContainer } from '#react-navigation/native'
import { createStackNavigator } from '#react-navigation/stack'
import Splash from '../views/Splash/Splash';
import Home from '../views/Home/Home';
const Stack = createStackNavigator()
function MainStackNavigator() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name='Splash' component={Splash} options={{ headerShown: false}} />
<Stack.Screen name='Home' component={Home} />
</Stack.Navigator>
</NavigationContainer>
)
}
export default MainStackNavigator
Splash.js
import React, { Component } from 'react'
import { View, ImageBackground, Image } from 'react-native'
// import SplashContext from '../../state/splashContext'
var bg = require('../../../assets/img/bg.png');
var logo = require('../../../assets/img/logo.png')
export default class Splash extends Component {
constructor(props) {
super(props);
setTimeout(() => {
this.props.navigation.navigate("Home");
}, 500)
}
render() {
return (
<ImageBackground
source={bg}
style={{ height: '100%', width: '100%' }}>
<View
style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Image source={logo}
style={{ height: 100, width: 100 }}
>
</Image>
</View>
</ImageBackground>
);
}
}
Home.js
import React, { Component } from 'react'
import { View, Text } from 'react-native'
export default class Splash extends Component {
render() {
return (
<View
style={{ flex: 1, padding: 10, alignItems: 'center', justifyContent: 'center' }}
>
<Text
style={{ fontSize: 30 }}
>Homse</Text>
</View>
);
}
}
App.js
import React from 'react';
import MainStackNavigator from './src/navigation/MainStackNavigator'
const App: () => React$Node = () => {
return (
<MainStackNavigator></MainStackNavigator>
);
};
export default App;
Using "navigate" will go to the next page adding it to the stack navigator. Instead you want to replace the current page (splash screen) with the home page. This can be done using
the replace function
this.props.navigation.replace("Home");
See https://reactnavigation.org/docs/navigation-prop/
You could use a modal to show the splash on the same screen while the information is loading instead of having two different views. Have a "loading" variable in the state of the view initialized to "true". This variable will be the "visibility" boolean for your modal. After everything loads, change the "loading" variable to "false".
Here's an example with "useState" hook:
const [isLoading, setIsLoading] = useState(true);
const loadInfo = async () => {
/*do your stuff*/
/*after stuff's done*/
setIsLoading(false);
};
if (isLoading) {
return (
<MySplashScreenModal/>
);
} else {
return (
<MyHomeScreen/>
);
}
The main reason for using the modal is because you can cover the entire screen with it, including the status bar.
I used this plugin for my android and ios app for the splash screen and it works great and smooth. I recommend everyone
React native bootsplash for splash screen
I am trying to learn React Native navigation. This is my App.js, and it works fine, as expected:
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
class App extends Component {
HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
render() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={this.HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
)
}
}
const Stack = createStackNavigator();
export default App;
Here I have defined HomeScreen in the App.js file itself. But what if I wanted to define it as a standalone component in another file (say HomeScreen.js), like so -
import React, { Component } from 'react';
import { View, Text } from 'react-native';
class HomeScreen extends Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
)
}
}
export default HomeScreen;
How would I import and use that HomeScreen in App.js? I have tried import HomeScreen from './components/HomeScreen' and <Stack.Screen name="Home" component={HomeScreen} /> but that gives me an error saying that it's not a component. I know this is a simple, basic question, but so far I've not been able to find an answer anywhere. Is there a different navigation library I should be using to solve this problem?
I fixed it. What I was trying to do is give the component value JSX style, like component={<HomeScreen />} but it should just be component={HomeScreen}.