Remove navigation header on screen for react native app - react-native

I want to remove header from my screen where I use bottom tab navigator.
Here is code example:
export class Home extends Component {
render() {
return <ProductList />;
}
}
export class Settings extends Component {
render() {
return <Chat />;
}
}
const Main = createBottomTabNavigator({
Home: {
screen: Home,
navigationOptions: {
header: null,
},
},
Settings: {
screen: Settings,
},
});
navigationOptions for header seams to be ignored
navigationOptions: {
header: null,
},
But when I use navigation option on single page without createBottomTabNavigator it works.
Any ideas?

You can use this instead of above
export class Home extends Component {
static navigationOptions = {
header: {
visible: false,
}
}
render() {
return <ProductList />;
}
}
export class Settings extends Component {
render() {
return <Chat />;
}
}
const Main = createBottomTabNavigator({
Home: {
screen: Home
},
Settings: {
screen: Settings,
},
},
{
headerMode: 'screen'
});
Hope this will help you

Related

How to use hook with SwitchNavigator

I'm trying to use https://github.com/expo/react-native-action-sheet with switch navigator.
I'm not sure how to do the basic setup as the example in the readme is different than my App.js. I'm using react 16.8 so I should be able to use hooks.
My App.js
import { useActionSheet } from '#expo/react-native-action-sheet'
const AuthStack = createStackNavigator(
{ Signup: SignupScreen, Login: LoginScreen }
);
const navigator = createBottomTabNavigator(
{
Feed: {
screen: FeedScreen,
navigationOptions: {
tabBarIcon: tabBarIcon('home'),
},
},
Profile: {
screen: ProfileScreen,
navigationOptions: {
tabBarIcon: tabBarIcon('home'),
},
},
},
);
const stackNavigator = createStackNavigator(
{
Main: {
screen: navigator,
// Set the title for our app when the tab bar screen is present
navigationOptions: { title: 'Test' },
},
// This screen will not have a tab bar
NewPost: NewPostScreen,
},
{
cardStyle: { backgroundColor: 'white' },
},
);
export default createAppContainer(
createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: stackNavigator,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
}
);
const { showActionSheetWithOptions } = useActionSheet();
);
Update, I'm getting this error when calling the showActionSheetWithOptions inside my component:
Hooks can only be called inside the body of a function component. invalid hook call
This is my code:
import React, { Component } from 'react';
import { useActionSheet } from '#expo/react-native-action-sheet'
export default class NewPostScreen extends Component {
_onOpenActionSheet = () => {
const options = ['Delete', 'Save', 'Cancel'];
const destructiveButtonIndex = 0;
const cancelButtonIndex = 2;
const { showActionSheetWithOptions } = useActionSheet();
showActionSheetWithOptions(
{
options,
cancelButtonIndex,
destructiveButtonIndex,
},
buttonIndex => {
console.log(buttonIndex);
},
);
};
render () {
return (
<View>
<Button title="Test" onPress={this._onOpenActionSheet} />
</View>
)
}
}
update 2
I also tried using a functional component, but the actionsheet does not open (console does print "pressed")
// ActionSheet.js
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
import { useActionSheet } from '#expo/react-native-action-sheet'
export default function ActionSheet () {
const { showActionSheetWithOptions } = useActionSheet();
const _onOpenActionSheet = () => {
console.log("pressed");
const options = ['Delete', 'Save', 'Cancel'];
const destructiveButtonIndex = 0;
const cancelButtonIndex = 2;
showActionSheetWithOptions(
{
options,
cancelButtonIndex,
destructiveButtonIndex,
},
(buttonIndex) => {
console.log(buttonIndex);
},
);
};
return (
<TouchableOpacity onPress={_onOpenActionSheet} style={{height: 100,}}>
<Text>Click here</Text>
</TouchableOpacity>
);
};
Problem
As you can see here. You are not connecting your application root component.
Solution
import connectActionSheet from #expo/react-native-action-sheet and connect your application root component to the action sheet.
Simply modify your App.js to reflect the following:
// ... Other imports
import { connectActionSheet } from '#expo/react-native-action-sheet'
const AuthStack = createStackNavigator({
Signup: SignupScreen,
Login: LoginScreen
});
const navigator = createBottomTabNavigator({
Feed: {
screen: FeedScreen,
navigationOptions: {
tabBarIcon: tabBarIcon('home'),
},
},
Profile: {
screen: ProfileScreen,
navigationOptions: {
tabBarIcon: tabBarIcon('home'),
},
},
});
const stackNavigator = createStackNavigator({
Main: {
screen: navigator,
// Set the title for our app when the tab bar screen is present
navigationOptions: { title: 'Test' },
},
// This screen will not have a tab bar
NewPost: NewPostScreen,
}, {
cardStyle: { backgroundColor: 'white' },
});
const appContianer = createAppContainer(
createSwitchNavigator({
AuthLoading: AuthLoadingScreen,
App: stackNavigator,
Auth: AuthStack,
}, {
initialRouteName: 'AuthLoading',
})
);
const ConnectApp = connectActionSheet(appContianer);
export default ConnectApp;
Now on any of your application screens (i.e. Feed, Profile, Main, etc.) you can access the action sheet as follows:
If Stateless Component
// ... Other imports
import { useActionSheet } from '#expo/react-native-action-sheet'
export default function Profile () {
const { showActionSheetWithOptions } = useActionSheet();
/* ... */
}
If Statefull Component
// ... Other imports
import React from 'react'
import { useActionSheet } from '#expo/react-native-action-sheet'
export default Profile extends React.Component {
const { showActionSheetWithOptions } = useActionSheet();
/* ... */
}
Note: You can also access the action sheet as stated below from the docs
App component can access the actionSheet method as this.props.showActionSheetWithOptions

React-navigation with a button in header

I'am trying to redirect to a profile page from a button in the header with react-navigation.
Here's what the createStackNavigator :
const NavigationApp = createStackNavigator({
Profile: { screen: ProfileScreenContainer },
Application: {
screen: Application,
navigationOptions: {
title: "Title",
headerStyle: {
backgroundColor: "#000",
},
headerTintColor: '#fff',
headerRight: (
<HeaderScreenContainer/>
),
},
},
},
{
initialRouteName: "Application"
});
const App = createAppContainer(NavigationApp);
export default App;
Here's my screen container for the header :
export default class HeaderScreenContainer extends Component {
constructor(props){
super(props);
}
render() {
return (<HeaderScreen profile={this.handleProfile.bind(this)} />);
}
handleProfile() {
this.props.navigation.navigate('Profile');
}
}
This is the button that I am rendering in header and that is supposed to redirect to the profile page.
export default class HeaderScreen extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Button onPress={() => this.props.profile()}>
<Text>Profile</Text>
</Button>
)
}
}
I am constantly getting the error : undefined is not an object (evaluating 'this.props.navigation.navigate').
Actually it's supposed to redirect to the profile page.
I believe you just need to wrap your HeaderScreenContainer in the withNavigation HOC like this...
class HeaderScreenContainer extends Component {
constructor(props){
super(props);
}
render() {
return (<HeaderScreen profile={this.handleProfile.bind(this)} />);
}
handleProfile() {
this.props.navigation.navigate('Profile');
}
}
export default withNavigation(HeaderScreenContainer)

React native: reset route, back to home page

My idea is to have 2 navigators:
StackNavigator - Home page, login page, sign up page
DrawerNavigator - pages for logged in users
Now, here's my code:
// App.js
import React, { Component } from 'react'
import { MainNavigator } from './src/components/main/MainNavigator'
import { UserNavigator } from './src/components/user/UserNavigator'
import { createSwitchNavigator, createAppContainer } from 'react-navigation'
export default class App extends Component {
constructor(props) {
super(props)
}
render() {
const Navigator = createAppContainer(
makeRootNavigator(this.state.accessToken)
)
return <Navigator />
}
}
const makeRootNavigator = (isLoggedIn) => {
return createSwitchNavigator(
{
Main: {
screen: MainNavigator
},
User: {
screen: UserNavigator
}
},
{
initialRouteName: isLoggedIn ? "User" : "Main"
}
)
}
Next, my MainNavigator.js:
import { createStackNavigator } from 'react-navigation'
import MainPage from './MainPage'
import LoginPage from './LoginPage'
export const MainNavigator = createStackNavigator({
Main: {
screen: MainPage
},
Login: {
screen: LoginPage
},
},
{
headerMode: 'none',
navigationOptions: {
headerVisible: false,
}
},
{
initialRouteName: "Main"
})
Login page has following relevant code:
export default class LogInPage extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<View style={styles.container}>
<LoginButton
onLoginFinished={
(error, result) => {
if (error) {
console.log("login has error: " + result.error);
} else if (result.isCancelled) {
console.log("login is cancelled.");
} else {
AccessToken.getCurrentAccessToken().then(
(data) => {
console.log(data.accessToken.toString())
this.props.navigation.navigate('User')
}
)
}
}
}
onLogoutFinished={() => console.log("logout.")}
/>
</View>
)
}
}
Now, that works like a charm. It takes me to my UserNavigator, which looks like this:
import { createDrawerNavigator } from 'react-navigation'
import ProfilePage from './ProfilePage'
import {MainNavigator} from '../main/MainNavigator'
export const UserNavigator = createDrawerNavigator({
Profile: {
screen: ProfilePage,
},
MainNavigator: {
screen: MainNavigator
}
},
{
initialRouteName: "Profile"
})
So, once I'm logged in, profile page properly shows up. Now, the problem is following: when I use logout button, it runs onLogoutFinished(), which is where I want to change navigation back to the main page, but can't seem to do it, whichever way I try. I tried both:
onLogoutFinished={() => {
console.log("logout.")
this.props.navigation.dispatch(NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'MainNavigator' })
]
}));
and
onLogoutFinished={() => {
console.log("logout.")
this.props.navigation.navigate('MainNavigator'));
}}
but both produce: Undefined is not an object ( evaluating '_this2.props.navigation.dispatch' ). Any ideas?

Using Tab and Stack Navigator Together

I am building an App on React-Native for which I am using React-Navigation
Now, Inside that i am using Stack-Navigation and TabNavigator (updated it DrawerNavigator)
import {
createStackNavigator,
TabNavigator,
DrawerNavigator
} from 'react-navigation';
import CoinCapCharts from "./src/container/CoinCapCharts.js"
import CoinCap from './src/container/CoinCap.js';
//THis is being Exported to App.js
export const Tab = TabNavigator({
TabA: {
screen: CoinCap
},
TabB: {
screen: CoinCap
}
}, {
order: ['TabA', 'TabB'],
animationEnabled: true,
})
export const MyScreen = createStackNavigator({
Home: {
screen: CoinCap
},
CoinCapCharts: {
screen: CoinCapCharts
}
},{
initialRouteName: 'Home',
headerMode: 'none'
});
export const Drawer = DrawerNavigator({
Tabs: { screen: Tab },
Stack: { screen: MyScreen },
})
I am importing this in my App.js where I am doing something like this
import React from 'react';
import {
Drawer
}from './Screen.js';
import {
View
} from 'react-native';
export default class App extends React.Component {
render() {
return (
<View>
<Drawer/>
<Tab/>
</View>
);
}
}
Now, This is indeed showing Tab the first time I run my app but after I navigate to different screen and return back, It doesn't appear to be showing that Tab again
[Question:] What could I be doing wrong and How can I fix it?
Try to define one within the other.
Something like:
const Tab = TabNavigator({
TabA: {
screen: Home
},
TabB: {
screen: Home
}
}, {
order: ['TabA', 'TabB'],
animationEnabled: true,
})
export const MyStack = createStackNavigator({
Home: {
screen: Home
},
CoinCapCharts: {
screen: CoinCapCharts
},
Tab: {
screen: Tab
},
},{
initialRouteName: 'Home',
headerMode: 'none'
});
Now, render MyStack (not sure that Screen is the best name :)
export default class App extends React.Component {
render() {
return (
<View>
<MyStack />
</View>
);
}
}

How to send parameters from screen to stack navigator?

I am a newbie to react native.
I am using a stack navigator inside a tab navigator; I have to navigate multiple screens inside each tab. i am able to send parameters from my default class HomePage to my nested classes in my tab and stack navigators.
export const MyApp = TabNavigator({
Asset: {
screen: AssetScreen,
},
Sensors: {
screen: sensorsStack,
},
Settings: {
screen: settingStack
},
}
export const sensorsStack = StackNavigator({
sensors : { screen: SensorScreen },
sensorDetails : { screen: SensorDetails }
});
export const settingStack = StackNavigator({
settings: { screen: SettingsScreen },
about : { screen: About },
environment : { screen: Environment }
});
export default class HomePage extends Component {
constructor(props) {
super(props);
this.state = {
assetID:'xyz',
authToken:'xyzz'
}
}
static navigationOptions = {
header: null
};
render() {
const screenProps = {
asset: {
assetID: this.state.assetID,
authToken : this.state.authToken,
},
}
return (
<MyApp screenProps={screenProps} />
);
}
}
Now, i want to send a parameter from 'SensorScreen' to 'SensorDetails'. I have tried sending parameters using
NavigationActions.navigate({ routeName: 'sensorDetails' ,params: { sensorType:'Fuel',}});
from 'SensorScreen' class. But was not able to get the parameter in 'SensorDetails' class. How can i pass this params?
A little late answer but might help others that ends up here.
Instead of using NavigationActions you could try navigation from sensorScreen to sensorDetails with navigate and passing some extra variables.
this.props.navigation.navigate('SensorDetails',{sensorType:'Fuel'})
The passed object can then be read in the second screen by
this.props.navigation.state.params.sensorType
A minimal example of the case can be seen in these lines. Observe that this is a stupid on icon tab bar. But it is kept that way since the question was about a tab bar with stacks on each tab. And new tabs are easily added.
import React,{Component} from 'react'
import { Text, View, Footer,Button } from 'react-native'
import {StackNavigator,TabNavigator} from 'react-navigation'
export class SensorScreen extends React.Component {
render() {
return (<Button
onPress={() => this.props.navigation.navigate('SensorDetails',{sensorType:'Fuel'})}
title="Go to Sensor Details"
/>)}}
export class SensorDetails extends React.Component {
render() {
return (<View>
<Text>{this.props.navigation.state.params.sensorType}</Text>
</View>);}
}
const sensorsStack = StackNavigator({
sensors : { screen: SensorScreen },
SensorDetails : { screen: SensorDetails }
});
const MyApp = TabNavigator({
Sensors: {
screen: sensorsStack,
},
});
export default class Nested extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<MyApp/>
);
}
}
Hope this helps.