React Native tabnavigation in seperate component? - javascript

I'm trying to make a RN-app, but I dont want to show the navigation on every screen. For example the registration and login screen shouldn't show the navigation. So I wanted to put the navigation in a component and import that component into the screens that should show it. I'm not sure if that works with navigation but I couldn't find anything saying that it won't work. I could be doing completely wrong.
The component I tried to create:
import React, { Component } from 'react'
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
class Navigation extends Component {
render() {
<Tab.Navigator>
<Tab.Screen name="Home" component={}/>
<Tab.Screen name="Explore" component={}/>
<Tab.Screen name="Account" component={}/>
</Tab.Navigator>
}
}
export default Navigation;
The way I wanted to import the component:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Navigation } from './components';
export default function App() {
return (
<View style={styles.container}>
<Navigation/>
</View>
);
}

I ever had the same issue. And this react navigation documentation is very helpful.
Please check here https://reactnavigation.org/docs/auth-flow/
If you just want keep the navigation and just need to hide the tab bar please read this one https://reactnavigation.org/docs/hiding-tabbar-in-screens

Related

Do we need to wrap all the screens with NativeBaseProvider in Native Base - React Native?

I have 3 screens here for example:
AuthScreen
HomeScreen
LoginScreen
AuthScreen.js, HomeScreen.js, LoginScreen.js
and have their respective content inside. And they are called by <Stack.Navigator> as shown in the link here
<NativeBaseProvider>
.
.
.
</NativeBaseProvider>
Is there a way I can just write the NativeBaseProvider once than have to do it on every screens?
NativeBaseProvider is a component that makes the theme available throughout your app. It uses React's Context API. Add NativeBaseProvider to the root of your app and update App.js as follows:
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { NativeBaseProvider } from 'native-base';
const Stack = createNativeStackNavigator();
export default function App() {
return (
<NativeBaseProvider>
<NavigationContainer>
<Stack.Navigator>{/* ... */}</Stack.Navigator>
</NavigationContainer>
</NativeBaseProvider>
);
}

Using a function with "navigate" as a compponent

I am trying to use navigation in react native, but it gives me an error when I try use a component with navigate (LogIn) with the
<Login/>
tags.
It says that navigate is undified so I passed the navigation as a prop with no success
App.js
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { SafeAreaView, StyleSheet, Text, View } from 'react-native';
import Login from "./assets/code/Login.js";
import { NavigationContainer, StackActions } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import 'react-native-gesture-handler';
const Stack = createStackNavigator();
export default function App({ navigation }) {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Welcome to dog app, and I hate react"
component={HomePage}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
function HomePage({ navigation }) {
return (
<View style={styles.container}>
<View>
<Text> {""}Welcome to dogappcoolapp app</Text>
</View>
<View style={styles.blue}>
<Login navigate={ navigation } style={styles.blue} />
</View>
</View>
)
}
The error is in this line
<Login navigate={ navigation } style={styles.blue} />
The error is
The LogIn function is in
LogIn.js
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, Script, Alert } from 'react-native';
import { NavigationContainer, StackActions, } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import 'react-native-gesture-handler';
const Stack = createStackNavigator();
export function Login({navigation}) {
if (true)
return (
navigation.navigate('WelcomePage')
);
}
function WelcomePage () {
return (
<View>
<Button title="enter" />
<Text> dog app dog woof-app{"\n\n\n\n\n\n\n\n\n"}OMG!! YOU ARE LOGGED IN! WELCOME!{"\n\n\n\n\n"}</Text>
</View>
);
}
const styles = StyleSheet.create({
blue: {
flex: 2,
backgroundColor: "dodgerblue",
alignItems: 'center',
justifyContent: 'center',
},
});
export default Login;
If I remove all of the navigation prop and tags from the function LogIn, then I can use LogIn as a componnent with <LogIn/>, but not with navigation, I tried usinng it with
navigate={ navigation }
(As it is in the code that I posted)
and I tried without it, I keep getting similar errors.
How can I use LogIn as a component with </> tags while still having navigation component in it?
The logic is correct, in child components, you can pass a navigation prop to get access to navigation, but you are passing your navigation object to a prop called navigate <Login navigate={ navigation } style={styles.blue} />, no wonder it's undefined, you should receive it as navigate in your Login component.
export function Login({navigation}) { //<-- here you have navigation where the prop name that you pass is navigate.
so it should be
export function Login({navigate}) {
...
navigate.navigate('...')
or you should rename your prop to navigation and then your navigation.navigate won't be undefined anymore.

React Native: How to change/navigate the Screen as a Childcomponent?

Every little help is appreciated very much!
I got an Avatar as a Navigator, which should allow me to navigate through some screens! Some other Screens should be reached only by the my home screen. But when I press on the Button in the Avatar, nothing happens. I don't understand how and why, but I believe I made a mistake in the stackNavigator somewhere? Just to avoid any misunderstanding, the code below is shortened to avoid filling the page with unnecessary information, so it doesn't reflect 1:1 what you see in the screenshots.
Home Screen which should change
Avatar Screen through which I should be able to change the Home Screen
The goal is to be able to change which Screen is displayed in the <AppContainer/> through the <Avatar/> component below.
I tried with a onPress function inside the Avatar.js to call this.props.navigation.navigate("Agenda") but the screen didn't change. At least I got rid of the errors thanks to passing the navigation prop. I believe I made kind of a scrub mistake since i'm not experienced with react native, I hope some of the more experienced users can help me with that :) furthermore I don't think the screen itself is important to solve this, it's just a class component with panresponder and animated view.
import React from "react";
import { StyleSheet, View, StatusBar } from "react-native";
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
import Avatar from "../coreComponents/Avatar";
import ScHome from "../screens/ScHome";
import ScNewMedi from "../screens/ScNewMedi";
import ScCalendar from "./ScAgenda";
const AppStack = createStackNavigator(
{
Home: {
screen: ScHome,
},
Medis: {
screen: ScNewMedi,
},
Agenda: {
screen: ScCalendar,
},
},
{
headerMode: "screen",
initialRouteName: "Home",
backBehavior: "order",
}
);
const AppContainer = createAppContainer(AppStack);
export default class ScDefault extends React.Component {
render() {
return (
<View style={styles.container}>
<StatusBar
barStyle="light-content"
backgroundColor="transparent"
translucent
/>
<AppContainer />
<Avatar navigation={this.props.navigation} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
The problem is you are trying to access navigation outside the Appcontainer where the navigation is not available.
Easy fix :
Moving the Avatar component inside one of your main screens(ScHome,ScNewMedi,ScCalendar) then you will have access to navigation and everything will work as expected.
Workaround :
Let say the requirement is to have the Avatar outside the AppContainer then you have to use something like a navigation service.
The code would be as below
let _navigator;
const setTopLevelNavigator=(navigatorRef) =>{
_navigator = navigatorRef;
}
const navigate=(routeName, params) =>{
_navigator.dispatch(
NavigationActions.navigate({
routeName,
params,
})
);
}
//Change your app.js
return <View style={{flex:1}}>
<AppContainer
ref={navigatorRef => {
setTopLevelNavigator(navigatorRef);
}}
/>
<Avatar navigate={navigate} /></View>;
//Inside the Avatar onPress you can can do this
onPress={()=>this.props.navigate("Home")}
You can refer the docs for more details

Nested switchNavigator inside a component with React Navigation

Im stuck with a Nested Navigation System. I have a main navigator (switchNavigator) and one of its screens is a component witch inside has some views and inside of one of this views I want to put another navigator (switchNavigator), but I get this error "The navigation prop is missing for this navigator. In react-navigation v3 and v4 you must set up your app container directly.". I really don't know if it's posible or a valid implementation.
This is my mainNavigator and two simple components, the second one is where I call the nested navigator:
import React from 'react';
import {createAppContainer,createSwitchNavigator} from 'react-navigation';
import { View, Text } from 'react-native';
import NestedNav from './nestedNav';
const FirstView = props=>{
return(
<View>
<Text>First view</Text>
</View>
)
}
const secondView = props=>{
return(
<View>
<View>
<Text>Second view</Text>
</View>
<View>
<NestedNav></NestedNav>
</View>
<View>
<Text>some other ui content</Text>
</View>
</View>
)
}
const MainNavigator = createSwitchNavigator(
{
firstView:FirstView,
secondView:secondView
},
{
initialRouteName: 'secondView',
}
);
export default createAppContainer(MainNavigator)
And this is my NestedNavigator:
import React from 'react';
import {createAppContainer,createSwitchNavigator} from 'react-navigation';
const NestedNav = createSwitchNavigator(
{
firstView:SomeFirstViewInNestedNav,
secondView:SomesecondViewInNestedNav
},
{
initialRouteName: 'firstView',
}
);
export default NestedNav
as you rendered the nestedNavigator it should be in wrapped into a appContainer.
const NestedNav = createSwitchNavigator(
{
firstView:SomeFirstViewInNestedNav,
secondView:SomesecondViewInNestedNav
},
{
initialRouteName: 'firstView',
}
);
--> export default createAppContainer(NestedNav)
I got the solution, I just had to create a static reference of the nested Navigation's Router in my nested navigator container component (in the example "secondView" component):
static router = NestedNav.router
And set the navigation prop to the nested navigator:
<NestedNav navigation = {this.props.navigation}></NestedNav>
This solution is in the Docs: here

reactnavigation hiding statusbar leaves space above header

I use reactnavigation and I am hiding the statusbar at the top, but it leaves an empty space above the header.
I already tried paddingTop or marginTop, but none work.
This is how I hide the statusbar.
import React from 'react';
import { Platform, View, StatusBar } from 'react-native';
import { Tabs, Drawer } from './config/router';
const App = () => (
<View style={{flex:1}}>
<StatusBar hidden={true} />
<Drawer />
</View>
);
export default App;
Any idea would be helpful.
Thanks.
How to Fix it
I add the following to the index.js:
import React from 'react';
import { Platform, View, StatusBar } from 'react-native';
import { Tabs, Drawer } from './config/router';
import { SafeAreaView } from 'react-navigation';
SafeAreaView.setStatusBarHeight(0);
const App = () => (
<View style={{flex:1}}>
<StatusBar hidden={true} />
<Drawer />
</View>
);
export default App;
Basically added the SafeAreaView part.
Hope this is helpful for others.
Try the static function Status Bar. You might need to convert the component to a React Component/Pure Component. Try it with and without converting it.
componentDidMount(){
StatusBar.setHidden(true,true);
}

Categories