I have a tab navigator inside a drawer navigator and I want to pass data from the draw navigator to a page in the tab navigator.
I tried passing a parameter in the DrawerContainer.js using
this.props.navigation.navigate('TabsNav', {testParam: 'TEST'})
and retrive it by this.props.navigation.getParam in the HomePage screen. But this did not work because the its navigating to the TabNav then rendering the HomePage.
How do I pass data to the tab navigator form the DrawerContainer.js then to the HomePage screen.
TabNav.js
export const Tabs = createMaterialTopTabNavigator(
{
HomePage: {
screen: Home,
},
ListView: {
screen: List,
},
},
{
order: ['HomePage', 'ListView'],
},
)
DrawerContainer.js
render() {
return (
<View style={styles.container}>
<View>
<TouchableHighlight
style={styles.TouchableHighlight}
onPress={this.props.navigation.navigate('TabsNav', {testParam: 'TEST'})}
<Text>Home</Text>
</TouchableHighlight>
</View>
<View>
<TouchableHighlight
style={styles.TouchableHighlight}
onPress={this.props.navigation.navigate('ProfilePage')}>
<Text>List View</Text>
</TouchableHighlight>
</View>
</View>
)
}
}
DrawNav.js
import { Tabs } from './TabNav.js'
import Profile from '../ProfilePage.js'
import DrawerContainer from '../DrawerContainer'
export const Draw = createDrawerNavigator(
{
TabsNav: {screen: Tabs},
ProfilePage: {screen: Profile},
},
{
contentComponent: DrawerContainer
},
);
HomePage.js
export default class HomePage extends Component{
componentWillMount(){
console.log(this.props.navigation.getParam('testParam', null))
}
render(){
<View>
</View>
}
}
you need to navigate to a screen specifically inside of the tab, not to the tab itself, or the params go into the tab navigator. params only go to the route that you are navigating to directly.
so
Drawer({
TabsNav: Tab({
HomePage: ScreenA,
ListView: ScreenB,
})
});
navigate to HomePage or ListView rather than TabsNav
this.props.navigation.navigate('HomePage', { testParam: 'Test' })
Or you can also Dispatch Navigation Actions for this purpose as follow:
import { NavigationActions } from 'react-navigation';
const navigateAction = NavigationActions.navigate({
routeName: 'HomePage',
params: { testParam: 'Test' }
});
this.props.navigation.dispatch(navigateAction);
I hope it help you.
Related
I'm new to react-native. I use react-native-side-menu to create a drawer and I add a bottom on the left side to skip to another page. when I push the bottom, the error code appeared. However, if I put the bottom in the homepage, it works. Why if I put it in the drawer it will crash?
This is route stack
App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { createStackNavigator, createAppContainer } from 'react-navigation';
import HomeScene from './homeScene';
import LoginScene from './loginScene';
import RegisterScene from './registerScene';
import TimetableScene from './timetable';
import ChatScene from './ChatScene';
import LeftMenu from './LeftMenu';
const SimpleApp = createStackNavigator({
Login: {
screen: LoginScene,
navigationOptions: {
headerTitle: 'Login',
}
},
Home: {
screen: HomeScene,
navigationOptions: {
header: null,
}
},
Register: {
screen: RegisterScene,
navigationOptions: {
headerTitle: 'Register',
}
},
Timetable: {
screen: TimetableScene,
navigationOptions:{
headerTitle: 'Timetable',
}
},
//The page I want to skip
Chat: {
screen: ChatScene,
navigationOptions:{
headerTitle: 'Chat',
}
}
LeftMenu:{
screen: LeftMenu
}
});
const AppContainer = createAppContainer(SimpleApp);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
LeftScene.js
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity,
SectionList
} from 'react-native';
export default class LeftMenu extends Component {
constructor(props) {
super(props);
this.selectSideMenu = this.selectSideMenu.bind(this);
}
selectSideMenu() {
this.props.onSelectMenuItem();
}
Chat = () => {
const { navigate } = this.props.navigation;
navigate('Chat');
}
render() {
return (
<View style={styles.container}>
//The bottom to skip to "Chat" page but will respond error
<TouchableOpacity
onPress={this.Chat}
style={styles.button}>
<Text
style={styles.btText}>Chat</Text>
</TouchableOpacity>
</View>
);
}
}
I think maybe the wrong code from the following code in LeftScene.js
Chat = () => {
const { navigate } = this.props.navigation;
navigate('Chat');
}
The this.props can only get the value from the parent component. The parent component of LeftMenu is homeScene, homeScene has no navigation so it doesn't work. And because of App.js is parent component of homeScene, so if I put the skip bottom in homeScene it can work. But I don't know how to figure out it...
homeScene.js
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
TextInput,
View,
TouchableOpacity,
Dimensions
} from 'react-native';
let { width, height } = Dimensions.get('window');
import SideMenu from 'react-native-side-menu'
import Menu from './LeftMenu'
export default class LeftSideMenu extends Component {
constructor(props) {
super(props);
this.state = {
isOpen: false,
}
this.SelectMenuItemCallBack = this.SelectMenuItemCallBack.bind(this);
}
SelectMenuItemCallBack() {
this.setState({
isOpen: !this.state.isOpen,
})
}
SelectToOpenLeftSideMenu() {
this.setState({
isOpen: true,
})
}
Chat = () => {
const { navigate } = this.props.navigation;
navigate('Chat');
}
render() {
const menu = <Menu onSelectMenuItem={this.SelectMenuItemCallBack} />;
return (
<SideMenu
menu={menu}
isOpen={this.state.isOpen}
onChange={(isOpen) => {
this.setState({
isOpen: isOpen,
})
}}
menuPosition={'left'}
openMenuOffset={0.75 * width}
edgeHitWidth={200}
>
<View
style={styles.top}>
//The bottom to open the drawer
<TouchableOpacity
onPress={() => this.SelectToOpenLeftSideMenu()}
style={styles.Fbutton} >
<Text
style={styles.btText}>F</Text>
</TouchableOpacity>
</View>
//The bottom to skip to "Chat" page and works
<View style={styles.container}>
<TouchableOpacity
onPress={this.Chat}
style={styles.button}>
<Text
style={styles.btText}>Chat</Text>
</TouchableOpacity>
</View>
</SideMenu>
);
}
}
I expect the bottom to skip to "Chat" page on the homeScene can be put in the drawer
You are facing this error because your LeftScene.js is not a part of your stack just add LeftScene.js in SimpleApp.
It will work.
Just change the code in homeScene.js
const menu = <Menu onSelectMenuItem={this.SelectMenuItemCallBack} />;
to the following
const menu = <Menu onSelectMenuItem={this.SelectMenuItemCallBack} navigation={this.props.navigation} />;
I have created modal in react native. I have added filter option icon in top right corner now when the user clicks on it should open the modal. How can I do that ? I have added Options icon in navigation.js but now how to connect it with modal component ?
In code below setModalVisible is available in filteroptions.js and not in navigation.js
Code:
navigation.js:
Updates: {
screen: UpdatesScreen,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Myapp',
headerRight:<TouchableOpacity onPress={() => {this.setModalVisible(true);}}>
<MenuIcon style={{paddingLeft: 10, paddingRight: 15}} name="md-options" size={25} color="white"/>
</TouchableOpacity>,
})
},
filteroptions.js:
import React, {Component} from 'react';
import {Modal, Text, TouchableHighlight, View, Alert} from 'react-native';
export default class FilteroptionsModel extends Component {
state = {
modalVisible: false,
};
setModalVisible(visible) {
this.setState({modalVisible: visible});
}
render() {
return (
<View style={{marginTop: 22}}>
<Modal
animationType="slide"
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}>
<View style={{marginTop: 22}}>
<View>
<TouchableHighlight
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}>
<Text>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
</View>
);
}
}
When user clicks on filter button in top right corner (see screenshot) he should be able to see the box modal on screen:
Since it is a modal you don't necessarily need to add it to the navigation. You can just include it in your page and initially have it be invisible, then when the user clicks your button you can make the modal visible. But if you want to add it to the navigation why not just add like any other component. However, adding it to the navigation will take you to another page when you navigate to the component. Of course you can add a nested navigator to work around that, but I think it adds unnecessary complexity.
Update
You will first declare a Header component.
export default class MyHeader extends React.PureComponent {
render() {
<View>
<View>...Your left Icon here</View>
<View>...Your Title here</View>
<View>...Your right Icon Here</View>
</View>
}
}
Then in your page you will render this component first, pass as props your handlers and then render the rest of the page.
export default class MyPage extends React.PureComponent {
yourRigthHandler = () => {
this.setState({modaVisible: true});
}
yourLeftHandler = () => {....}
render() {
<View>
<MyHeader
LeftHandler={yourLeftHandler}
LeftHandler={yourRigthHandler}>
....
</MyHeader>
</View>
}
}
inside the handlers you can call the navigation functions to navigate to another page or change the components state to make the moda visible.The handlers will be passed as props to your header and you will add them as onPress handlers to your buttons.
I've just set up a React Navigation TabNavigator which works fine but I'm having issues with transitions between my views.
I get the following error message from trying to redirect the user to another page after a click on a button.
Cannot read property 'navigate' of undefined
I'm super confused on how to make this work.
Here is the navigator:
import React from 'react';
import { TabNavigator, StackNavigator } from 'react-navigation';
import ElemList from './src/components/ElemList';
import ElemShow from './src/components/ElemShow';
const RootTabs = TabNavigator({
Home: {
screen: ElemList,
navigationOptions: {
tabBarLabel: 'Home',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-home' : 'ios-home-outline'}
size={26}
style={{ color: tintColor }}
/>
),
},
main: {
screen: StackNavigator({
show: { screen: ElemShow },
})
}
}
});
Here is my code:
onRowPress(data) {
this.props.navigation.navigate('ElemShow', {id: data})
};
render() {
const { key, elem } = this.props;
return (
<TouchableWithoutFeedback onPress={() => this.onRowPress(elem)}>
<View style={styles.viewStyle} key={key}>
<Text>Here is the info</Text>
</View>
</TouchableWithoutFeedback>
)
}
The problem is with this line
this.props.navigation
Should be
this.props.navigator
Additionally I don't know that navigate is part of the screens API; typically you will use push or resetTo.
I'm on ReactNative and i'm using native-base and react-navigation npm.
I got this and my question is how I can have a header, up to the button "Home", I looked into the documentation of react-navigation but it's not really cleared.
https://github.com/react-community/react-navigation/blob/master/docs/api/navigators/DrawerNavigator.md
Like this (the image is fix, it's just to put a logo here)
You can implement custom content component for drawer. There you can also simply render navigation items using DrawerItems. For example:
import React from 'react'
import { Text, View } from 'react-native'
import { DrawerItems, DrawerNavigation } from 'react-navigation'
const DrawerContent = (props) => (
<View>
<View
style={{
backgroundColor: '#f50057',
height: 140,
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text style={{ color: 'white', fontSize: 30 }}>
Header
</Text>
</View>
<DrawerItems {...props} />
</View>
)
const Navigation = DrawerNavigator({
// ... your screens
}, {
// define customComponent here
contentComponent: DrawerContent,
})
For Drawer Navigation, you Can add Your own Header & Footer and Make Your Own Styles with contentComponent Config:
First import { DrawerItems, DrawerNavigation } from 'react-navigation' Then
Header Before DrawerItems:
contentComponent: props => <ScrollView><Text>Your Own Header Area Before</Text><DrawerItems {...props} /></ScrollView> .
Footer After DrawerItems:
contentComponent: props => <ScrollView><DrawerItems {...props} /><Text>Your Own Footer Area After</Text></ScrollView> .
You can achieve it using contentComponent option in drawer nav config. Two ways you could do it based on the level of configuration required:
Method 1.
DrawerItems from react-navigation(handles navigation on its own) -
import {DrawerItems, DrawerNavigation} from 'react-navigation';
export default DrawerNavigator({
// ... your screens
}, {
// define customComponent here
contentComponent: (props) =>
<View style={{flex: 1}}>
<Text>Header</Text>
<ScrollView>
<DrawerItems {...props} />
</ScrollView>
</View>
});
This creates a fixed header with scroll view for the menu items below it.
Method 2.
Creating your own custom component -
import { DrawerNavigation } from 'react-navigation'
export default DrawerNavigator({
// ... your screens
}, {
// define customComponent here
contentComponent: props => <SideMenu {...props}>
});
Here SideMenu is your own component to display in the drawer. You can use react-navigation NavigationActions.navigate(screen) to handle routing on onPress of menu items.
For more detailed explanation on the second method https://medium.com/#kakul.gupta009/custom-drawer-using-react-navigation-80abbab489f7
nested navigator should be like this:
const Router = StackNavigator({
Home: {screen: HomeScreen},
Test: {screen: TestScreen}
}, {
navigationOptions: {
headerStyle: {backgroundColor: '#2980b9'},
headerTintColor: '#fff'
}
});
const Drawer = DrawerNavigator({
App: {screen: Router}
});
for ui:
1) https://github.com/GeekyAnts/native-base-react-navigation-stack-navigator/blob/master/src/SideBar/SideBar.js
2) https://github.com/GeekyAnts/native-base-react-navigation-stack-navigator/blob/master/src/HomeScreen/index.js
I'm currently working with React Native and there I've got a question about React Navigation and the StackNavigator. I would like to add a custom close button to the header, but I'm not sure how to do this.
It's just possible for me to navigate to the screens, but not for example to go back or dispatch something.
On my example the navigationOptions for the HomeScreen is working. The drawer opens and the SettingsButton navigates to the settings screen. But I've got problems with the navigationOptions of the EntryScreen. There I build a CloseButton to go back, but I need access to the navigation object.
With navigate it's possible to navigate to other screens, but I need access to the parent object navigation. For example on the class for the drawer it's possible to get access through props.navigation (For example props.navigation.navigate('Home') or props.navigation.goBack(null))
This is a part of my current code. Of course it's currently not working because of the missing access to navigation:
const Stack = StackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: {
header: ({ navigate }) => ({
left: <DrawerButton navigate={navigate} />,
right: <SettingsButton navigate={navigate} />
})
}
},
Entry: {
screen: EntryScreen,
navigationOptions: {
header: ({ navigation }) => ({
right: <CloseButton navigate={navigation } />
})
}
}
})
export const Drawer = DrawerNavigator({
Home: {
screen: Stack
}},
{
contentComponent: HamburgerMenu
}
)
These are the buttons:
export const CloseButton = (props) => {
let testButton = <TouchableHighlight onPress={() => props.navigation.goBack(null)}>
<Icon name='close' style={styles.headerButtonIcon} />
</TouchableHighlight>
return testButton
}
export const SettingsButton = (props) => (
<TouchableHighlight onPress={() => props.navigate('Settings')}>
<Icon name='more-vert' style={styles.headerButtonIcon} />
</TouchableHighlight>
)
Maybe you can help me there. Thanks in advance!
I've found the answer thanks to the help of sigmazen on Github.
Instead of navigation I have to put goBack into the header for the CloseButton. After this I'm able to use it through props.goBack(null)
Entry: {
screen: EntryScreen,
navigationOptions: {
title: `Eintrag`,
header: ({ goBack }) => ({
right: <CloseButton goBack={goBack} />
})
}
},
export const CloseButton = (props) => {
let test = <TouchableHighlight onPress={() => props.goBack(null)}>
<Icon name='close' style={styles.headerButtonIcon} />
</TouchableHighlight>
return test
}