I tried navigate react-native-navigation with timer. So if the value of the timer is '5', navigation to 'Home' is called.
I used ternary operation to call navigation.
import React from 'react';
import {
View,
Text,
Button
} from 'react-native';
import {styles} from './AppStyle'
import {createStackNavigator, createAppContainer} from 'react-navigation'
import HomeScreen from './Pages/Home'
class Timer extends React.Component{
constructor(props){
super(props)
this.state = {
time : props.count
}
}
componentDidMount(){
this.addInterval = setInterval( () => this.increase(), 1000)
}
componentWillUnmount(){
clearInterval(this.addInterval)
}
increase(){
this.setState((_state, _props) => ({
time: parseInt(this.state.time) + 1
}))
}
render(){
return(
<Text> {this.state.time} </Text>
);
}
}
class StartScreen extends React.Component {
render(){
return (
<View style={styles.container}>
<View style={styles.navbar}>
<Timer count='0'/>
{this.props.count == '5' ? ()=>this.props.navigation.navigate('Home') : ''}
</View>
</View>
);
};
}
const HomeNavigator = createStackNavigator(
{
Home: {
screen: HomeScreen
}
}
)
const StartNavigator = createStackNavigator(
{
Start: {
screen: StartScreen
},
Main: {
screen: HomeNavigator
}
},
{
mode: 'modal',
headerMode: 'none'
},
{
initialRouteName: 'Start'
}
)
const AppContainer = createAppContainer(StartNavigator);
export default class App extends React.Component {
render() {
return <AppContainer/>
}
}
I expect when count is '5' screen will navigate to 'Home', but i got this issue "Invariant Violation: Invariant Violation: Text Strings must be rendered within a component"
Create an onIncrease prop for your Timer component, rather than directly making the function call within render.
class Timer extends React.Component {
/* component functions */
increase = () => {
const { time } = this.state
const { onIncrease } = this.props
const newTime = time + 1
onIncrease(newTime)
this.setState({ time: newTime })
}
/* render function */
}
class StartScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.navbar}>
<Timer
count={0}
onIncrease={count => {
if (count === 5) {
this.props.navigation.navigate('Home')
}
}}
/>
</View>
</View>
)
}
}
You can also use setTimeout, instead of doing:
{this.props.count == '5' ? ()=>this.props.navigation.navigate('Home') : ''}
you can do
{ setTimeout(()=>{ this.props.navigation.navigate("Home") }, 3000);}
Related
Current Behavior
I am trying to have a tab navigator, where one of the screens/tabs has a component, that, among other stuff, has a stack navigator in it.
However, I currently get a 'No "routes" found in navigation state' error.
How to reproduce
The code I'm currently running can also be found as a snack.
Code:
import * as React from 'react';
import { Button, Text, View, StyleSheet } from 'react-native';
import { createAppContainer, createStackNavigator, createBottomTabNavigator } from 'react-navigation';
class ScreenA extends React.Component {
static navigationOptions = {
tabBarLabel: 'A',
};
render() {
return (
<View>
<Text>Screen A</Text>
</View>
);
}
}
class SettingsHome extends React.Component {
render() {
return (
<Button onPress={() => this.props.navigation.navigate('SettingsScreenA')}>
<Text>Navigate to Settings A</Text>
</Button>
);
}
}
class SettingsScreenA extends React.Component {
render() {
return (
<View>
<Text>Settings A</Text>
<Button onPress={() => this.props.navigation.navigate('SettingsA')}>
<Text>Back to SettingsHome</Text>
</Button>
</View>
);
}
}
const SettingsStackNavigator = createStackNavigator({
SettingsHome: { screen: SettingsHome },
SettingsScreenA: { screen: SettingsScreenA }
})
class SettingsScreen extends React.Component {
static navigationOptions = {
tabBarLabel: 'Settings',
}
render() {
return (
<View>
<Text>Some other components...</Text>
<SettingsStackNavigator navigation={this.props.navigation}/>
</View>
);
}
}
const RootTabNavigator = createBottomTabNavigator({
ScreenA: { screen: ScreenA },
Settings: {screen: SettingsScreen },
});
const Navigation = createAppContainer(RootTabNavigator);
export default class App extends React.Component {
render() {
return (
<Navigation />
);
}
}
in this button you want to navigate to SettingsA
<Button onPress={() => this.props.navigation.navigate('SettingsA')}>
<Text>Back to SettingsHome</Text>
</Button>
but you defined the route of Settings screen as Settings
const RootTabNavigator = createBottomTabNavigator({
ScreenA: { screen: ScreenA },
Settings: {screen: SettingsScreen },
});
you have to fix it by change the SettingsA as route name in tab navigator
const RootTabNavigator = createBottomTabNavigator({
ScreenA: { screen: ScreenA },
SettingsA: {screen: SettingsScreen },
});
I want to send images from one page to another with react native navigations
here are my codes
this is app.js file which is the main file to initialized react navigations and pages
App.js
import React from "react"
import Walkthrought1 from "./Pages/Walkthrought1/Walkthrought1.js"
import Walkthrought2 from "./Pages/Walkthrought2/Walkthrought2.js"
import {createAppContainer} from "react-navigation"
import {createStackNavigator} from "react-navigation-stack"
const PushRouteOne = createStackNavigator({
Page1: {
screen: Walkthrought1,
},
Page2: {
screen:Walkthrought2,
},
/*
Page3:{
screen:Walkthrough03,
},
Login: {
screen:Register,
}*/
},
{
initialRouteName: "Page1",
mode: "modal",
headerMode: "none",
})
const AppContainer = createAppContainer(PushRouteOne)
export default class App extends React.Component {
render() {
return <AppContainer/>
}
}
And the another pages Walkthrought1 which is the list of images and select the image and send it to walkthrought2
Walkthrought1.js
const products = [
{
id:'1',
title:'Product1',
image: require("./assest/image1.jpg"),
},
{
id:'2',
title:'Product2',
image:require("./assest/image2.jpg"),
},
{
id:'3',
title:'Product3',
image:require("./assest/image3.jpg"),
},
{
id:'4',
title:'Product4',
image:require("./assest/image4.jpg"),
},
{
id:'5',
title:'Product5',
image:require("./assest/image5.jpg"),
},
{
id:'6',
title:'Product6',
image:require("./assest/image7.jpg"),
},
{
id:'7',
title:'Product7',
image:require("./assest/image8.jpg"),
},
{
id:'8',
title:'Product8',
image: require("./assest/image9.jpg"),
},
];
function Item({ id,title,image,selected,onSelect }) {
return (
<TouchableOpacity
onPress={() => {
const {navigate} = this.props.navigation;
navigate("Page2",{
Send_Image:image,
Send_Title:title,
});
}}>
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
<Image style={styles.images} source={image}/>
</View>
</TouchableOpacity>
);
}
export default class Walkthrought1 extends React.Component {
static navigationOptions = ({ navigation }) => {
const { params ={} } = navigation.state
}
constructor(props)
{
super(props)
}
render(){
return (
<SafeAreaView>
<FlatList
numColumns={2}
data={products}
renderItem={({ item }) =>
<Item
title={item.title}
image={item.image}
/> }
keyExtractor={item => item.id}
extraData={selected}
/>
</SafeAreaView>
);
}
}
and this is Walkthrought2.js this page showing image which is come from walkthrought1 with navigation
Walkthrought2.js
import 'react-native-gesture-handler';
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import {
Image,
StyleSheet,
View,
Text,
} from 'react-native';
import {
//responsiveheight,
responsiveWidth,
responsiveFontSize,
responsiveHeight,
} from "react-native-responsive-dimensions";
export default class Walkthrought2 extends React.Component {
static navigationOptions = ({ navigation }) => {
const { params ={} } = navigation.state
}
constructor(props)
{
super(props)
}
componentDidMount() {
const Get_Image = (this.props.navigation.params("Send_Image"));
const Get_Title = (this.props.navigation.params("Send_Title"));
}
render() {
return (
<NavigationContainer>{<View>
<Image style={styles.images} source={require(Get_Image)}/>
<Text style={styles.title}>{Get_Title}</Text>
</View>}</NavigationContainer>
);
}
}
And when I ran i've given this error
I'm currently working on an app in React-Native and it includes DrawerNavigation, SwitchNavigation and AppContainer. There is a method at header.js that i need to use in order to make the drawer functionable (toggleDrawer())
I've tried passing the function at the DrawerNavigator but it didnt work.
export default class Header extends React.Component {
render() {
return (
<View style={styles.container}>
<TouchableOpacity
onPress={() => {
this.props.navigation.toggleDrawer();
}}
>
<Image
source={require("/Users/Rron/AnketaApp/assets/hamburger-
icon.jpg")}
style={styles.imageStyle}
/>
</TouchableOpacity>
</View>
);
}
}
});
export default class HomeScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
let drawerLabel = "Home";
return { drawerLabel };
};
render() {
return (
<View style={styles.container}>
<Header {...this.props}/>
<ScrollView>
<Content />
</ScrollView>
</View>
);
}
}
export default class DrawerNavigator extends React.Component {
render() {
return <AppContainer />;
}
}
const AppDrawerNavigator = createDrawerNavigator(
{
Home: {
screen: HomeScreen
},
Anketa: {
screen: AnketaScreen
}
}
);
const AppContainer = createAppContainer(
createSwitchNavigator({
Introduction: {
screen: IntroductionScreen
},
Drawer: {
screen: AppDrawerNavigator``
}
})
);
The error says
this.props.navigation.toggleDrawer is not a function and its not
defined.
What you can do is import { DrawerActions } from 'react-navigation-drawer' and use it as it says in the docs.
this.props.navigation.dispatch(DrawerActions.toggleDrawer());
Also make sure that you components are inside the navigation.
I have a requirement of using Redux in Tabnavigator which is inside of
an DrawerNavigator.Redux Portion is working fine, But I am unable to
open the drawer on click of a button but the drawer is visible on
swipe gesture.
I am providing my code:-
App.js:-
import * as React from 'react';
import {createAppContainer,createStackNavigator,createBottomTabNavigator} from 'react-navigation';
import RegisterStack from './routes/Register.route';
import SplashStack from './routes/Splash.route';
import Test from './src/pages/Test';
const AppNavigator = createStackNavigator(
{
Splash: SplashStack,
Register: RegisterStack,
StartTest :Test
},
{
initialRouteName: 'StartTest',
headerMode:'none'
});
let Navigation = createAppContainer(AppNavigator);
export default class App extends React.Component {
render() {
return (
<Navigation />
);
}
}
code in Test.js:-
import React from 'react';
import { View,StyleSheet,Text,SafeAreaView,Dimensions,Button } from 'react-native';
import {createAppContainer,createMaterialTopTabNavigator,createDrawerNavigator, DrawerActions} from 'react-navigation';
import ReferenceStack from './Reference';
import QuestionStack from './Question';
import { Provider, connect } from 'react-redux';
import { createStore, combineReducers } from 'redux';
function counter(state, action) {
if (typeof state === 'undefined') {
return 0;
}
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
let store = createStore(combineReducers({ count: counter }));
class DrawerLayout extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<SafeAreaView style={styles.container}>
<Text>{this.props.count}</Text>
<Button
title="Increment"
onPress={() => this.props.dispatch({ type: 'INCREMENT' })}
/>
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
container: {
flex:1,
backgroundColor: "red",
}
});
let CounterContainer = connect(state => ({ count: state.count }))(ReferenceStack);
let StaticCounterContainer = connect(state => ({ count: state.count }))(QuestionStack);
let StaticCounterContainerDrawer = connect(state => ({ count: state.count }))(DrawerLayout);
const DrawerStack = createDrawerNavigator({
Test: {
screen: createMaterialTopTabNavigator({
Reference: {
screen: CounterContainer
},
Question:{
screen: StaticCounterContainer
}
},{
tabBarPosition: 'bottom',
tabBarOptions:{
activeTintColor:'#d61822',
inactiveTintColor:'#5e5e5e',
pressColor:'#d61822'
}
})
}
},{
drawerPosition: "left",
drawerWidth: Dimensions.get('screen').width*.80,
contentComponent: StaticCounterContainerDrawer
});
let DrawerTabNavigation = createAppContainer(DrawerStack);
class Test extends React.Component {
constructor(props) {
super(props);
console.log(props)
}
render() {
return (
<View style={{flex:1}}>
<View style={{height:50,backgroundColor:'yellow'}}></View>
<Provider store={store}>
<DrawerTabNavigation/>
</Provider>
<View style={{height:50,backgroundColor:'yellow'}}>
<Button
title="Open Drawer"
onPress={() => this.props.navigation.toggleDrawer()}
/>
</View>
</View>
);
}
}
export default Test;
When ever Open Drawer button is pressed
_this3.props.navigation.toggedrawer is not a function this error is showing.
I am providing the screen and the error also:-
Please hekp me to open the drawer on click of a button. Thanks in
advance
this.props.navigation.toggedrawer will work only for the screens which are in DrawerNavigator.
May be try this.
import { DrawerActions } from "react-navigation";
this.props.navigation.dispatch(DrawerActions.toggleDrawer())
Im doing this inside the react native platform using expo.
I want to display the list of items ( ListItems.js) All_Employees_screen.js . These items are being rendered via a functional component, I want to have a onRowPress() handler to so that upon clicking it i can navigate it to another view, but I dont know how to do it on react-navigation ?
Or since the new functional component can be a class component( this would be better ) how can i access the navigation thing inside it ?
AllProperties.js
import _ from 'lodash';
import React, {
Component
} from 'react';
import {
Button,
ListView,
ScrollView
} from 'react-native';
import ListItem from './ListItem';
import { connect } from 'react-redux';
import { propertiesFetch } from '../../actions';
// import { FormLabel, FormInput } from 'react-native-elements'
class AllPropertiesScreen extends React.Component {
componentWillMount(){
this.props.propertiesFetch();
this.createDataSource(this.props);
}
// we do this componentWillMount & componentWillReceiveProps (nextProps) thing twice, coz once the component is
// loaded it loads all teh values but when user hits another view like Create property, The Property data still exists
// in the global state object,
// we could move all the dc dataSource code into componentWillReceiveProps but its actually gonna benefit us
// if we make sure that we try to build our data source both when the component first loads up
// & when second time after we go back and forth other compoennts.
componentWillReceiveProps(nextProps){
// nextProps are the next set of props that this component will be rendered with
// this.props is still the old set of props
this.createDataSource(nextProps);
}
createDataSource({ properties }){
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
this.dataSource = ds.cloneWithRows(properties);
}
static navigationOptions = ({ navigation }) => {
const {state, setParams} = navigation;
return {
title: 'All Emplooyee',
headerRight: (
<Button
title='Add'
// onPress={() => setParams({ mode: isInfo ? 'none' : 'info'})}
onPress={() => navigation.navigate('createProperty')
}
/>
),
};
};
goBack(){
console.log('65 - go Back clicked');
}
renderRow(property){
// console.log('67-AllPropertiesScreen =', property);
return <ListItem property={property}
onPress={() => { console.log('65 - go Back clicked') }}
/>;
}
render() {
console.log('72-AllPropertiesScreen this.props', this.props );
return(
<ListView
enableEmptySections
dataSource={this.dataSource}
renderRow={this.renderRow}
/>
);
}
}
const mapStateToProps = state => {
console.log('83 - AllPropertiesScreen state. properties', state );
const properties = _.map(state.properties, (val, uid ) => {
return { ...val, uid }; // { shift: 'Monday'}
});
return { properties };
};
export default connect(mapStateToProps, {propertiesFetch}) (AllPropertiesScreen);
ListItem.js
import React, { Component } from 'react';
import { Text, TouchableWithoutFeedback, View } from 'react-native';
class ListItem extends Component {
// onRowPress(){
// Actions.employeeEdit({ employee: this.props.employee });
// }
render(){
const { agent_name, cell, address } = this.props.property;
console.log('14- ListItem ', this.props);
return (
<View>
<CardSection>
<Text style={styles.titleStyle}>
name
</Text>
<Text style={styles.titleStyle}>
cell
</Text>
<Text style={styles.titleStyle}>
address
</Text>
</CardSection>
</View>
);
}
}
const styles = {
titleStyle: {
fontSize: 18,
paddingLeft: 15
}
}
export default ListItem;
//
main.js ( this is where I have all the navigation paths hookedup.
class App extends React.Component {
render() {
const MainNavigator = TabNavigator({
// auth: { screen : AuthScreen },
// review: { screen: ReviewScreen },
// signup: { screen : SignupScreen },
followup: { screen: FollowupScreen }, welcome: { screen : WelcomeScreen },
auth: { screen : AuthScreen },
signup: { screen : SignupScreen },
main: {
screen: TabNavigator ({
followup: { screen: FollowupScreen },
map: { screen: MapScreen },
deck: { screen: DeckScreen },
settings : {
screen: StackNavigator ({
settings: { screen: SettingsScreen },
// settings: { screen: SettingsScreen },
UserProfile: { screen: UserProfileScreen },
HelpSupport: { screen: HelpSupportScreen },
Notifications: { screen: NotificationsScreen },
Signout: { screen: SignoutScreen } // not working, Navigation object not accessible inside the component
}) //screen: StackNavigator ({
},
followup : {
screen: StackNavigator ({
followup: { screen: FollowupScreen },
allProperties: { screen: AllPropertiesScreen },
createProperty: { screen: PropertyCreateScreen },
Red: { screen: RedPriorityScreen }, // not working, Navigation object not accessible inside the component
GreyPriority: { screen: GreyPriorityScreen },
}) //screen: StackNavigator ({
},
draw: {
screen: DrawerNavigator ({
drawin: { screen: DrawScreen },
}) //screen: StackNavigator ({
}
}) //screen: TabNavigator
}
}, {
navigationOptions: {
tabBarVisible: false
},
lazy: true
});
return (
<Provider store={store}>
<View style={styles.container}>
<MainNavigator />
</View>
</Provider>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
// alignItems: 'center',
justifyContent: 'center',
},
});
Expo.registerRootComponent(App);
Solution suggested by #Matt but as soon as I put the navigation={this.props.navigation} it complains. undefined is not an object ( evaluating this.props.navigation )
renderRow(property){
return (
<ListItem
property={property}
navigation={this.props.navigation}
onPress={() => {
console.log( '70-on Press inside renderRow ');
}}/>
);
}
If the component is not a screen you have to import the navigation.
Try this:
import React from 'react';
import { Button } 'react-native';
import { withNavigation } from 'react-navigation';
class MyBackButton extends React.Component {
render() {
return <Button title="Back" onPress={() => { this.props.navigation.goBack() }} />;
}
}
// withNavigation returns a component that wraps MyBackButton and passes in the
// navigation prop
export default withNavigation(MyBackButton);
For more info check out
https://reactnavigation.org/docs/connecting-navigation-prop.html
This answer was written for old version of react-navigation V1
I had the same exact problem, and I found out that this.props.navigation is injected only in components that are registered as screen in StackNavigator or TabbNavigator.
but in general you can use navigate from NavigationActions class (source here https://v1.reactnavigation.org/docs/navigation-actions.html#navigate)
note: NavigationActions.navigate receives parameters in different way but works the same way.
so this working for me
import { NavigationActions } from 'react-navigation';
let {navigate} = NavigationActions;
renderRow(property) {
return (
<ListItem
property={property}
onPress={() => { navigate({
routeName: 'OtherRoute'
});
}}/>
);
}
<MyComponent navigation={this.props.navigation}/>
Main problem is here. You didn't define your prop navigation in component. You should add this.
Here's how you can use navigation.navigate inside a functional component:
import { Text, TouchableHighlight } from 'react-native';
const MyComponent = ({ navigation }) => (
<TouchableHighlight
onPress={() => navigation.navigate('OtherRoute')}
underlayColor="blue"/>
<Text>Click to Navigate!</Text>
</TouchableHighlight>
);
export default MyComponent;
When you render MyComponent, you will need to pass navigation as a prop. For example, assume HomeContainer is a screen component:
import React from 'react';
import MyComponent from './MyComponent';
export default HomeContainer extends React.Component {
render() {
return (
<MyComponent navigation={this.props.navigation}/>
);
}
}
Change your renderRow method to the following:
renderRow(property) {
return (
<ListItem
property={property}
onPress={() => { this.props.navigation.navigate('OtherRoute'); }}/>
);
}
where 'OtherRoute' is the name of the route you want to navigate to for that row.