I would like to use my onLogin() function to navigate to the Dashboard view of the Android MVP I'm building. I've been thrown into a React Native project despite not knowing it and I've only just begun my career, so the answer is probably painfully obvious, but after lots of research I can't quite work it out! Hopefully one of you can guide me to the solution.
I've copied the Login view below.
import React, { Component } from 'react';
import {
TouchableHighlight,
TextInput,
Text,
View,
Image
} from 'react-native';
import styles from "./../style/CustomStylesheet";
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
Email: '',
password: '',
};
}
onLogin() {
const { Email, password } = this.state;
//insert function to navigate to dashboard here?
}
render() {
return (
<View style={styles.container}>
<Image
style={styles.logo}
source={require('./../../android/app/src/main/res/drawable/login.png')}
/>
<TextInput
value={this.state.Email}
onChangeText={(Email) => this.setState({ Email })}
placeholder={'Email'}
placeholderTextColor={'#333333'}
style={styles.input}
inlineImageLeft='login_id'
/>
<TextInput
value={this.state.password}
onChangeText={(password) => this.setState({ password })}
placeholder={'Password'}
placeholderTextColor={'#333333'}
secureTextEntry={true}
style={styles.input}
inlineImageLeft='login_password'
/>
<View style={styles.help}>
<Text>Need help?</Text>
</View>
<TouchableHighlight
style={[styles.input, styles.button]}
onPress={this.onLogin.bind(this)}>
<Text style={styles.buttonText}>LOGIN</Text>
</TouchableHighlight>
<View style={styles.modal}>
<Text style={styles.modalText}>New user?</Text>
<Text style={styles.modalText}>Register on our web app or our iPad app</Text>
</View>
</View>
);
}
}
I've added the dashboard to my Stack Navigation file too. Any guidance you could give would be wonderful. Many thanks!
import Login from "./Login";
import Dashboard from "./Dashboard";
const AppNavigator = createStackNavigator(
{
Home: { screen: Login },
Dashboard: { screen: Dashboard }
},
{
headerMode: 'none'
}
);
export default createAppContainer(AppNavigator);
add this
onLogin=()=> {
const { Email, password } = this.state;
const { navigation } = this.props;
navigation.navigate('Dashboard');
}
I use TabNavigator and DrawerNavigator both in my app.
When I open drawer with 'slide' option, contents slide with drawer but TabBar doesn't slide together.
I want to make TabBar slide together but I cannot find any option about it.
How Can I do this?
Could you help?
-------------[code]----------------
1) app.js
...skip ...
const DailySalesStack = createStackNavigator({
DailySalesMain: DailySalesMain,
},
{
defaultNavigationOptions:{
header:null
},
initialRouteName:'DailySalesMain'
});
const DailyRivalRankStack = createStackNavigator({
DailyRivalRankMain: DailyRivalRankMain,
},
{
defaultNavigationOptions:{
header:null
},
initialRouteName:'DailyRivalRankMain'
});
const SalesAnalysisStack = createStackNavigator({
SalesAnalysisMain: SalesAnalysisMain,
},
{
defaultNavigationOptions:{
header:null
},
initialRouteName:'SalesAnalysisMain'
});
const DailySalesAnalysisStack = createStackNavigator({
DailySalesAnalysisMain: DailySalesAnalysisMain,
},
{
defaultNavigationOptions:{
header:null
},
initialRouteName:'DailySalesAnalysisMain'
});
/// DRAWER!
const SalesStack = createDrawerNavigator({
DailySales: {
screen: DailySalesStack,
},
DailyRivalRank: {
screen: DailyRivalRankStack,
},
SalesAnalysis: {
screen: SalesAnalysisStack,
},
DailySalesAnalysis: {
screen: DailySalesAnalysisStack,
},
},
{
contentComponent:SalesSlideMenu,
drawerType: 'slide',
drawerWidth:230*REM,
}
);
...skip...
/// BOTTOM TAB
export default createAppContainer(createBottomTabNavigator(
{
MainStack:MainStack,
ApprovalStack:ApprovalStack,
SalesStack:SalesStack,
OrganizationStack:OrganizationStack,
SettingStack:SettingStack,
},
{
tabBarComponent: TabBar,
}
));
2) tabBar.js
const TAB_LIST = [
require('../../resources/images/tabIcon_main.png'),
require('../../resources/images/tabIcon_approval.png'),
require('../../resources/images/tabIcon_sales.png'),
require('../../resources/images/tabIcon_organization.png'),
require('../../resources/images/tabIcon_settings.png'),
];
export default class TabBar extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log("[TabBar.js] : Render ====");
const {
onTabPress,
navigation
} = this.props;
const { routes, index: activeRouteIndex } = navigation.state;
return (
<SafeAreaView style={{backgroundColor:'rgb(250,250,250)'}}>
<View style={styles.rootContainer}>
{routes.map((route, routeIndex) => {
const isRouteActive = routeIndex === activeRouteIndex;
return (
<TouchableWithoutFeedback key={routeIndex} onPress={() => {onTabPress({ route });}}>
<View style={styles.tabIconContainer}>
<Image style={[styles.icon,isRouteActive&&{tintColor:'black'}]} source={TAB_LIST[routeIndex]} resizeMode={'contain'}/>
{/* <View style={[styles.badge]}><Text style={[styles.text,styles.badgeNumber]}>12</Text></View> */}
</View>
</TouchableWithoutFeedback>
);
})}
</View>
</SafeAreaView>
);
}
}
3) SlideMenu.js
const MENU_LIST = [
{'icon':require('../../resources/images/dailySales.png'),'label':'Daily Sales','subLabel':'','route':'DailySales'},
{'icon':require('../../resources/images/rivalRank.png'),'label':'Daily Rival Rank','subLabel':'','route':'DailyRivalRank'},
{'icon':require('../../resources/images/salesAnalysis.png'),'label':'Sales Analysis','subLabel':'','route':'SalesAnalysis'},
{'icon':require('../../resources/images/dailySalesAnalysis.png'),'label':'Daily Sales Analysis','subLabel':'','route':'DailySalesAnalysis'},
]
class SlideMenuTab extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<View style={{flex:0}}>
<TouchableWithoutFeedback onPress={()=>this.props.navigation.navigate(this.props.data.route+"Main")}>
<View style={[styles.tabContainer,this.props.focused&&{backgroundColor:'rgb(247,247,247)'}]}>
<Image style={styles.tabIcon} source={this.props.data.icon} resizeMode={'contain'}/>
<View style={styles.labelContainer}>
<Text style={[styles.text,styles.label]}>{this.props.data.label}</Text>
<Text style={[styles.text,styles.subLabel]}>{this.props.data.subLabel}</Text>
</View>
</View>
</TouchableWithoutFeedback>
</View>
)
}
}
export default class SalesSideMenu extends React.Component {
constructor(props) {
super(props);
console.log("[SalesSideMenu.js] : Constructor");
}
render() {
console.log("[SalesSideMenu.js] : render ====");
let menuList = [];
MENU_LIST.forEach((data)=>{
let focused = this.props.activeItemKey === data.route;
menuList.push(
<SlideMenuTab data={data} focused={focused} navigation={this.props.navigation}/>
);
})
return (
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<View style={styles.rootContainer}>
{menuList}
</View>
</SafeAreaView>
);
}
}
4) Screen with drawer
export default class DailySalesMain extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log("[DailySalesMain.js] : render ====");
return (
<View style={{flex:1,backgroundColor:'white',alignItems:'center',justifyContent:'center'}}>
<TouchableWithoutFeedback onPress={()=>this.props.navigation.openDrawer()}>
<View style={{width:'100%',height:50}}>
<View style={{width:50,height:50,backgroundColor:'blue'}}></View>
</View>
</TouchableWithoutFeedback>
<Text>DailySalesMain</Text>
</View>
);
}
}
If youre ussing React Native... This should be the default behaviour at least in iOS. Android Material Design supports the Drawer as a design desition, so if you want to hide the TabBar, just make a custom one or include the TabBar inside the Drawer.
But warning, hidding the TabBar may sometimes bring errors in Apple Store when you upload your app for revision.
From the TabBar section in the Human Interface Guidelines of iOS....
Don't hide a tab bar when people navigate to different areas in your app. A tab bar enables global navigation for your app, so it should remain visible everywhere. The exception to this is in modal views. Because a modal view gives people a separate experience that they dismiss when they're finished, it's not part of the overall navigation of your app.
Use badging to communicate unobtrusively. You can display a badge—a red oval containing white text and either a number or an exclamation point—on a tab to indicate that new information is associated with that view or mode.
In other words.. if you plan to support iOS in your apps, you should try to always show the TabBar somehow, or the store might give you some usability complains like this one.
We noticed that several screens of your app were crowded or laid out in a way that made it difficult to use your app.
Please see attached screenshot for reference.
Next Steps
To resolve this issue, please revise your app to ensure that the content and controls on the screen are easy to read and interact with.
I'm trying 'DrawerLayoutAndroid' in react native with inside the drawer I added the react-navigation 'stackNavigator' to navigate between screen.What I'm trying to do
but the problem is when I navigate it opens in the drawer
How do I open it full screen as a normal page
Is there a better method to achieve this
(redux state ?)
Thank you in advance
I found a solution
what I did is created a routing page and added it as the root component
routes.js
import Main from '../screens/main';
import Ad from '../screens/adView';
export const AdNav = StackNavigator({
Home:{screen:Main,
navigationOptions:{
header:null,
}
},
Ad:{screen:Ad,
navigationOptions:{
title:'Details',
}}
}
);
App.js
import {AdNav} from './src/config/routes';
export default class App extends Component<{}> {
render() {
return (
<View style={styles.container}>
<AdNav />
</View>
);
}
}
Then I added DrawerLayoutAndroid to the main screen
inside the drawer layout I used stackNavigator to navigate with no issues
main screen with DrawerLayoutAndroid
render() {
var navigationView = (
<View style={{flex: 1}}>
<Button onPress={()=>this.props.navigation.navigate('Ad')} title="go to next page"/>
</View>
);
return (
<DrawerLayoutAndroid
drawerWidth={300}
drawerPosition={DrawerLayoutAndroid.positions.Left}
renderNavigationView={() => navigationView}>
<View style={styles.container}>
{/*content*/}
</View>
</DrawerLayoutAndroid>
);
}
}
I want to set up a sidebar menu with Drawer (Native Base).
I have a App.js :
export default class ReactProject extends Component {
renderScene (route, navigator) {
return <route.component navigator={navigator} />
}
render() {
return (
<Navigator
style={styles.container}
renderScene={this.renderScene.bind(this)}
initialRoute={{component: Home}}
/>
);
}
}
A Home.js with the drawer :
export default class Home extends Component {
render() {
return (
<Drawer
ref={(ref) => { this._drawer = ref; }}
content={<SideBar />} navigator={this.props.navigator}>
<Container>
</Container>
</Drawer>
);
}
}
And sidebar.js which is loaded into the drawer :
export default class SideBar extends Component {
constructor(props) {
super(props);
}
redirect(routeName){
this.props.navigator.push({
component: routeName
});
}
render() {
return (
<Content style={styles.sidebar}>
<ListItem button >
<Text>Home</Text>
</ListItem>
<ListItem button >
<Text>Test</Text>
</ListItem>
<ListItem button onPress={this.redirect.bind('Blank')}>
<Text>Blank Page</Text>
</ListItem>
</Content>
);
}
}
But when I click i have this error:
Undefined is not an object (evaluating 'this.props.navigator.push')
I do not have this problem when the button is in the page but only in the sidebar.js
Could someone help me?
thank you,
Thomas.
I think you have to change little bit code of your Home.js as per mentioned below:
render() {
return (
<Drawer
ref={(ref) => { this._drawer = ref; }}
content={<SideBar navigator={this.props.navigator} />}
<Container>
</Container>
</Drawer>
);
And add this lines of code in your sidebar.js file:
static propTypes = {
navigator: React.PropTypes.object,
}
I am learning react-native navigation https://reactnavigation.org/docs/intro/ . I see in examples there
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Text>Hello, Chat App!</Text>
<Button
onPress={() => navigate('Chat')}
title="Chat with Lucy"
/>
</View>
);
}
}
I could not understand what exactly this line of code is for const { navigate } = this.props.navigation;
syntax has nothing to do with React Native
it is called Destructuring assignment in es6 / es2015
const { navigate } = this.props.navigation;
is equivilent to with exception to var and const .
var navigate = this.props.navigation.navigate
the example without Destructuring should look like this
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
return (
<View>
<Text>Hello, Chat App!</Text>
<Button
onPress={() => this.props.navigation.navigate('Chat')}
title="Chat with Lucy"
/>
</View>
);
}
}
Include on your ServiceAction the this.props.navigation something like this:
<HomeScreen navigation={this.props.navigation}/>
because the props.navigation are by default on your parent component
and on HomeScreen component you will access to navition like:
..
goToSignUp() {
this.props.navigation.navigate('SignUp');
}
..
For me also was confusing before. Cheers!