I have my next splash, my idea is to be able to show my app logo when opening the application and then go to the start of the application, it works fine:
import React from 'react';
import { StyleSheet, Image, View, Text } from 'react-native';
import { StackActions, NavigationActions } from 'react-navigation';
export default class Splash extends React.Component {
goToScreen(routeName){
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: routeName })],
});
this.props.navigation.dispatch(resetAction);
}
/*goToScreen(routeName){
this.props.navigation.navigate(routeName)
}*/
componentDidMount(){
setTimeout( () => {
this.goToScreen('Home')
}, 2000, this)
}
render(){
return (
<View style={styles.container}>
<Image source={{uri: 'https://i.imgur.com/r0jUwOD.png'}} style={{width: 250, height: 250}} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#33B747',
alignItems: 'center',
justifyContent: 'center'
},
});
The problem is the location of the splash, since in this way if it shows me, but it creates a lower button called Splash, on the other hand the splash when loading is shown in conjunction with the lower buttons and that should not happen, the splash must display only in full screen and not create a button.
AppNavigator.js
import React from 'react';
import { createStackNavigator } from 'react-navigation-stack';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { createAppContainer } from 'react-navigation';
import { MaterialIcons, MaterialCommunityIcons } from '#expo/vector-icons';
import Splash from '../screens/Splash';
import NewsListScreen from '../screens/NewsListScreen';
import NewsItemScreen from '../screens/NewsItemScreen';
const StackNavigator = createStackNavigator({
Splash: {
screen: Splash,
navigationOptions: {
headerShown: false,
}
},
News: {
screen: NewsListScreen
},
Root: {
screen: BottomTabNavigator,
},
NewsItem: {
screen: NewsItemScreen,
navigationOptions: {
headerTitle: 'News Item'
}
},
},{
initialRouteName: 'Splash'
});
const BottomTabNavigator = createBottomTabNavigator({
Home: {
screen: StackNavigator,
navigationOptions: {
tabBarIcon: () => <MaterialIcons name="home" size={24} />
}
},
News: {
screen: StackNavigator,
navigationOptions: {
tabBarIcon: () => <MaterialCommunityIcons name="newspaper-variant-outline" size={24} />
}
}
})
export default createAppContainer(BottomTabNavigator);
App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { AppLoading } from 'expo';
import { Provider } from 'react-redux';
import AppNavigator from './app/resources/navigation/AppNavigator';
import ReduxStore from './app/resources/redux/ReduxStore';
export default function App() {
return (
<Provider store={ReduxStore}>
<AppNavigator />
</Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Attached capture of the error upload in imgur capture 1 and capture 2
The recommended way to add a splash screen to an expo managed app can be found here.
I've managed to create an expo project and achieve the exact same behavior that you've looking for.
I've used react-navigation 4.x.x
This is how it looks and you can find the full code here
Here is the code I've used.
Splash.js
import React, { Component } from "react";
import { Text, SafeAreaView, View, StyleSheet } from "react-native";
import { StackActions, NavigationActions } from "react-navigation";
export class Splash extends Component {
goToScreen(routeName) {
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: routeName })],
});
this.props.navigation.dispatch(resetAction);
}
componentDidMount() {
setTimeout(
() => {
this.goToScreen("Root");
},
2000,
this
);
}
render() {
return (
<SafeAreaView style={styles.mainContainer}>
<Text style={styles.text}> Splash Screen </Text>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#efef21",
},
text: {
fontSize: 22,
},
});
export default Splash;
Navigator.js
import { createStackNavigator } from "react-navigation-stack";
import { createAppContainer } from "react-navigation";
import Home from "./Home";
import Splash from "./Splash";
import TabNavigator from "./BottomTabNavigator";
const AppNavigator = createStackNavigator(
{
Splash: {
screen: Splash,
navigationOptions: {
headerShown: false,
},
},
Root: {
screen: TabNavigator,
navigationOptions: {
headerShown: false,
},
},
},
{
initialRouteName: "Splash",
}
);
export default createAppContainer(AppNavigator);
BottomTabNavigator.js
import { createAppContainer } from "react-navigation";
import { createBottomTabNavigator } from "react-navigation-tabs";
import Home from "./Home";
import News from "./News";
const TabNavigator = createBottomTabNavigator({
Home: {
screen: Home,
navigationOptions: {
title: "Home",
},
},
News: {
screen: News,
navigationOptions: {
title: "News",
},
},
});
export default createAppContainer(TabNavigator);
Also, I've achieved the same behavior using react-navigation 5.x.x
You can find my code here
Edit 01
If you want to have the headers, You need to use a Stack Navigator for each tab.
Here is the updated code of BottomTabNAvigator.js
import { createAppContainer } from "react-navigation";
import { createBottomTabNavigator } from "react-navigation-tabs";
import { createStackNavigator } from "react-navigation-stack";
import Home from "./Home";
import News from "./News";
const HomeStack = createStackNavigator({
Home: Home,
});
const NewsStack = createStackNavigator({
News: News,
});
const TabNavigator = createBottomTabNavigator({
Home: {
screen: HomeStack,
navigationOptions: {
headerTitle: "Home",
title: "Home",
},
},
News: {
screen: NewsStack,
navigationOptions: {
title: "News",
},
},
});
export default createAppContainer(TabNavigator);
You have used Splash: {screen: Splash}, in your BottomTabNavigator so obviously it will add splash as on bottom navigator.
Remove Splash: {screen: Splash}, from BottomTabNavigator and paste it on StackNavigator and set splash as initialRouteName
const StackNavigator = createStackNavigator({
News: {
screen: NewsListScreen
},
Splash: {screen: Splash},
NewsItem: {
screen: NewsItemScreen,
navigationOptions: {
headerTitle: 'News Item'
}
},
},
{
initialRouteName : 'Splash'
});
you have to move splash screen to StackNavigator and add BottomTabNavigator into StackNavigator as a screen like this
import React from 'react';
import { createStackNavigator } from 'react-navigation-stack';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { createAppContainer } from 'react-navigation';
import { MaterialIcons } from '#expo/vector-icons';
import Splash from '../screens/Splash';
import NewsListScreen from '../screens/NewsListScreen';
import NewsItemScreen from '../screens/NewsItemScreen';
const StackNavigator = createStackNavigator({
Splash: {
screen: Splash
},
Home: {
screen: BottomTabNavigator
},
News: {
screen: NewsListScreen
},
NewsItem: {
screen: NewsItemScreen,
navigationOptions: {
headerTitle: 'News Item'
}
}
},
{
initialRouteName: "Splash",
});
const BottomTabNavigator = createBottomTabNavigator({
Home: {
screen: StackNavigator,
navigationOptions: {
tabBarIcon: () => <MaterialIcons name="home" size={24} />
}
}
})
export default createAppContainer(StackNavigator);
Related
I create two tabs.
Here is my react-navigation configure setting:
navigator/index.ts
import { createAppContainer, createSwitchNavigator } from 'react-navigation';
import RootScreen from '../components/RootScreen';
import MainStack from './MainStack';
const RootStack = createSwitchNavigator(
{
RootScreen: RootScreen,
MainStack: MainStack
},
{
initialRouteName: 'RootScreen',
}
)
const AppContainer = createAppContainer(RootStack);
export default AppContainer;
navigator/MainStack.ts
import { createStackNavigator } from 'react-navigation-stack';
import TabsStack from './TabsStack'
const MainStack = createStackNavigator(
{
tabs: TabsStack,
},
{
// headerMode: 'none',
}
);
export default MainStack;
navigator/TabsStack.tsx
import React from 'react';
import { Image } from 'react-native';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import HomeScreen from '../components/HomeScreen/HomeScreen';
import SettingScreen from '../components/SettingScreen/SettingScreen';
import LoveIcon from '../assets/image/heart.png';
const TabsStack = createBottomTabNavigator(
{
HomeScreen: {
screen: HomeScreen,
navigationOptions: {
title: 'Home',
tabBarLabel: 'HomeTab',
tabBarIcon: ({ focused, tintColor }) => {
return <Image {...with some props}/>
},
}
},
SettingScreen: {
screen: SettingScreen,
navigationOptions: {
tabBarLabel: 'STab',
tabBarIcon: ({ focused, tintColor }) => {
return <Image {...with some props}/>
},
}
},
},
{
tabBarOptions: {
showLabel: true,
activeTintColor: 'blue',
inactiveTintColor: 'black',
style: {
// with some style
}
},
}
);
export default TabsStack;
And I try to set header title on my HomeScreen.tsx by using static navigationOptions
import React from 'react';
import { View, Text } from 'react-native';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'HomeScreen Header',
};
render() {
return (
<View>
<Text>I am HomeScreen</Text>
</View>
);
}
}
export default HomeScreen;
My HomeScreen header shows tabs.
It looks like static navigationOptions is not working.
What's wrong with my react-navigation settings ?
Just use this way:
import React from 'react';
import { View, Text } from 'react-native';
class HomeScreen extends React.Component {
componentDidMount() {
this.props.navigation.setOptions({ title: 'HomeScreen Header' });
};
render() {
return (
<View>
<Text>I am HomeScreen</Text>
</View>
);
}
}
export default HomeScreen;
I have a drawer and bottom tab nav system on my app which works perfectly, but I"ve come to a point where I have modules where I want a button click to take the user to a page for data entry but I don't want that page on any nav bars, I just need to route to it on button press.
So in App.js i have my existing nav system:
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View, Image } from 'react-native';
import Splash from './Splash';
import Login from './src/components/Login/Login';
import Dashboard from './src/components/Dashboard/Dashboard';
import Trends from './src/components/Trends/Trends';
import EnterWeight from './src/components/Dashboard/EnterWeight';
import Profile from './src/Profile';
import {createAppContainer, createSwitchNavigator} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs';
import { createDrawerNavigator } from 'react-navigation-drawer';
import Icon from '#expo/vector-icons/Ionicons';
import * as SQLite from 'expo-sqlite';
const db = SQLite.openDatabase('testDatabase');
const DashboardTabNavigator = createMaterialBottomTabNavigator({
Dashboard: {screen:Dashboard},
Trends: {screen:Trends},
//Profile: {screen:Profile},
EnterWeight: {screen:EnterWeight}
},
{
barStyle: { backgroundColor: '#000'},
},
{
navigationOptions:({navigation})=>{
const {routeName} = navigation.state.routes[navigation.state.index]
return{
headerTitle:routeName
}
}
}
);
const DashboardStackNavigator = createStackNavigator({
DashboardTabNavigator: DashboardTabNavigator
},
{
defaultNavigationOptions:({navigation}) => {
return {
headerLeft: (<Icon style={{paddingLeft:10}} onPress={()=>navigation.openDrawer()} name="md-menu" size={30} />),
headerRight: (<Image style={styles.crossLogo} source={require('./src/images/LOGO-cross_only.png')}/>)
}
}
});
const AppDrawerNavigator = createDrawerNavigator({
Dashboard:{screen:DashboardStackNavigator},
Logout:{screen:Login}
});
const AppSwitchNavigator = createSwitchNavigator({
Login:{screen: Login},
Dashboard:{screen:AppDrawerNavigator},
},
{
initialRouteName: 'Login',
});
export default class MMH_App_Final extends Component{
render() {
const App = createAppContainer(AppSwitchNavigator);
return(
<App />
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
crossLogo: {
width:30,
height:30,
marginRight:10
}
});
But on another page I have
<TouchableOpacity
style={styles.recordButton}
onPress={() => navigate('EnterWeight')}
>
I want to be able to navigate to EnterWeight without registering it in the navbar. How can I do that?
a simple way to do this is to manage order on your TabNavigator:
const DashboardTabNavigator = createMaterialBottomTabNavigator({
Dashboard: {screen:Dashboard},
Trends: {screen:Trends},
//Profile: {screen:Profile},
EnterWeight: {screen:EnterWeight}
},
{
barStyle: { backgroundColor: '#000'},
},
{
navigationOptions:({navigation})=>{
const {routeName} = navigation.state.routes[navigation.state.index]
return {
headerTitle: routeName,
order: [
'Dashboard',
'Trends',
//'Profile',
],
}
}
}
);
But you have other options like :
Create a custom TabNavigator
Reorder your stack implementation to
isolate this new screen
Environment
React native: 0.61
react-native navigation:4.0
Deployed os : Android 9 pie
import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import Signup from './Signup';
import React, { Component } from 'react';
import Home from './Home';
import EditProfile from './Editprofile';
import Payments from './Payments';
import Refer from './Refer';
import { createDrawerNavigator } from 'react-navigation-drawer';
export default class App extends React.Component {
render() {
return <Appcont />;
}
}
const appi = createStackNavigator(
{
signup: {
screen: ()=><Signup/>
},
home: {
screen: ()=><Home/>
},
editProfile:{
screen:()=><EditProfile/>
},
payments:{
screen:()=><Payments/>
},
refer:{
screen:()=><Refer/>
}
},
{
initialRouteName:'signup'
}
);
const MyDrawerNavigator = createDrawerNavigator(appi,{
initialRouteName: 'signup',
headerMode:'float',
contentOptions: {
activeTintColor: '#e91e63',
}
});
const Appcont = createAppContainer(MyDrawerNavigator);
home.js
import React, { Component } from 'react';
import { Text, View,Image } from 'react-native';
class Home extends Component {
static navigationOptions = {
title:'Home',
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<Image
source={require('./img/Homepng.png')}
style={{width:20,height:20}}
/>
),headerShown:'true'
};
render() {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Hello, home</Text>
</View>
);
}
}
export default Home;
When I run the above code it throws me an error !!!
Error The component for the router must be a react component
I have seen all the issues related to this and rectified as much I can but I am still getting this error I don't know why?
you can try to change the
const appi = createStackNavigator(
{
signup: {
screen: ()=><Signup/>
},
}
to
const appi = createStackNavigator({
signup: {
screen: Signup,
},
});
At the same time ,the Singup have to extend React.Component, and remember export it. and () => <Home/> is not a component. it is function object
export defalut class Sigup extends React.component
I'm building an app in react-native. I'm trying to set initial route name dynamically in my navigation with switchNavigator. Here is my code :
Navigation.js
import { createStackNavigator, createAppContainer, createSwitchNavigator } from 'react-navigation'
import homeDisconnect from '../screens/homeDisconnect.js'
import Login from '../screens/Login'
import Register from '../screens/Register'
import Home from '../screens/Home'
import AuthLoading from '../screens/AuthLoading'
const AppStack = createStackNavigator(
{
Home: {
screen: Home,
navigationOptions: {
headerTitle: 'Accueil',
headerLeft: null,
gesturesEnabled: false
}
}
}
)
const AuthStack = createStackNavigator(
{
homeDisconnect: {
screen: homeDisconnect,
navigationOptions: {
headerTitle: null,
headerLeft: null,
header: null
}
},
Login: {
screen: Login,
navigationOptions: {
headerTitle: 'S\'identifier',
headerLeft: null
}
},
Register: {
screen: Register,
navigationOptions: {
headerTitle: 'S\'inscrire'
}
}
},
{
headerLayoutPreset: 'center',
initialRouteName: 'homeDisconnect'
}
)
export default createAppContainer(createSwitchNavigator(
{
AuthLoading: AuthLoading,
AppStack: AppStack,
AuthStack: AuthStack,
}
));
AuthLoading.js
import React, { Component } from 'react'
import {ActivityIndicator, StatusBar, StyleSheet, View} from 'react-native'
import {AppStack, AuthStack} from '../navigation/StackNavigation'
import { connect } from 'react-redux'
class AuthLoading extends Component {
constructor() {
super();
}
componentDidMount(){
this._bootstrapAsync()
}
_bootstrapAsync = async () => {
console.log(this.props)
const userToken = this.props.token
this.props.navigation.navigate(userToken ? 'App' : 'Auth');
};
render() {
return (
<View style={styles.container}>
<ActivityIndicator />
<StatusBar barStyle="default" />
</View>
);
}
}
const mapStateToProps = (state) => {
return state
}
export default connect(mapStateToProps)(AuthLoading);
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
App.js
import {AuthLoading} from './src/screens/AuthLoading'
export default class App extends Component {
render() {
return (
<View>
<AuthLoading></AuthLoading>
</View>
)
}
}
--> import {AppStack, AuthStack} from '../navigation/StackNavigation', is it not possible to do that, that way ? I'm getting that error :
The component for route 'AuthLoading' must be a React component.
What am I doing wrong ?
SwitchNavigator knows to navigate between screen/stack in the same SwitchNavigator, so i recommended to navigate in this way:
userToken ?
this.props.navigation.navigate('AppStack') : this.props.navigation.navigate('AuthLoading')
and you don't need this import so remove it:
import {AppStack, AuthStack} from '../navigation/StackNavigation'
Navigation.js:
export default MainNavigator = createSwitchNavigator(
{
AuthLoading: AuthLoading,
AppStack: AppStack,
AuthStack: AuthStack,
}
});
Now change your code in App.js :
import MainNavigator from './src/screens/AuthLoading'
export default class App extends Component {
render() {
return (
<View>
<MainNavigator />
</View>
)
}
}
I've build an app with a BottomTabNavigator and createSwitchNavigator.
If I declare my screen inside the MainTabNavigator, the top header of my screens work as intended, but as soon as I import my screens (for example my HomeScreen) I get a double header.
I've tried adding:
{
headerMode: 'none',
navigationOptions: {
headerVisible: false,
}
}
To my StackNavigator, but doesn't seem to have an effect.
I've tried looking at similar posted questions, but have not been set off into the right direction.
Is anyone else familiar with this problem and how to solve it?
App JS
import React from 'react';
import { View, Text } from 'react-native';
import { createStackNavigator,createBottomTabNavigator } from 'react-navigation';
import AppNavigator from './navigation/AppNavigator';
export default class App extends React.Component {
render() {
return <AppNavigator />;
}
}
App Navigator
import React from 'react';
import { createSwitchNavigator } from 'react-navigation';
import MainTabNavigator from './MainTabNavigator';
export default createSwitchNavigator(
{
Main: MainTabNavigator,
},
);
MainTabNavigator
import React from 'react';
import { Button, Text, View } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation';
import HomeScreen from '../screens/clubs/Home';
import DetailsScreen from '../screens/clubs/Details';
class SettingsScreen extends React.Component {
static navigationOptions = {
// title: ' Alpha',
header: null,
};
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
);
}
}
const HomeStack = createStackNavigator({
Home: { screen: HomeScreen },
Details: { screen: DetailsScreen },
});
const SettingsStack = createStackNavigator({
Settings: { screen: SettingsScreen },
Details: { screen: DetailsScreen },
});
export default createBottomTabNavigator(
{
Home: { screen: HomeStack },
Settings: { screen: SettingsStack },
},
{
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Home') {
iconName = `ios-information-circle${focused ? '' : '-outline'}`;
} else if (routeName === 'Settings') {
iconName = `ios-information-circle${focused ? '' : '-outline'}`;
}
return <Ionicons name={iconName} size={25} color={tintColor} />;
},
}),
tabBarOptions: {
activeTintColor: '#DD016B',
inactiveTintColor: 'white',
tabStyle: {
width: 100,
backgroundColor: 'black',
},
labelStyle:{
color: 'white',
},
}
},
);
Home JS
import React, { Component } from 'react';
import {
AppRegistry,
ListView,
View,
Text,
StyleSheet,
Image,
Button,
TouchableOpacity,
TextInput,
ScrollView,
Icon,
FlatList,
} from 'react-native';
import { createStackNavigator, } from 'react-navigation';
export class HomeScreen extends Component {
static navigationOptions = {
// title: ' Alpha',
header: null,
};
....... App content
}
AppRegistry.registerComponent('App', () => App)
export default createStackNavigator({
Home: {
screen: HomeScreen,
},
},
{
initialRouteName: 'Home',
});
In your MainTabNavigator file, try this:
const HomeStack = createStackNavigator({
Home: { screen: HomeScreen, navigationOptions: { header: null } },
Details: { screen: DetailsScreen, navigationOptions: { header: null } },
});