React Navigation failed. No errors - reactjs

I'm trying to navigate from tab page to other page. I'm following tabnavigator and stacknavigator.
myTabsHost(RegisterHostPage) Here I'm hosting two tabs
import React, { Component } from "react";
import {
AppRegistry,
Text,
View,
Image,
StyleSheet,
TouchableOpacity
} from "react-native";
import { TabNavigator } from "react-navigation";
import { Tab } from "../../config/router.js";
import {Tab2} from "../../config/router.js";
import { NavigationActions } from "react-navigation";
class RegisterHost extends Component {
render() {
return (
<View style={Styles.container}>
<Text style={Styles.boldLabel}> User Register</Text>
<Text style={Styles.normalLabel}>Wallet account registration</Text>
<TouchableOpacity
onPress={() => {
const navigateAction = NavigationActions.navigate({
key: null,
routeName: "preactivate",
params: {}
});
this.props.navigation.dispatch(navigateAction);
}}
>
<Text>topreactivate</Text>
</TouchableOpacity>
<Tab2 />
</View>
);
}
}
const Styles = StyleSheet.create({
container: {
flex: 1,
padding: 2,
justifyContent: "center",
backgroundColor: "#FFFFFF"
},
boldLabel: {
fontWeight: "bold",
fontSize: 24,
alignSelf: "center",
color: "#08AE9E",
marginBottom: 20,
marginTop: 10
},
normalLabel: {
fontWeight: "normal",
fontSize: 18,
alignSelf: "center",
color: "black",
marginBottom: 20,
marginTop: 10
}
});
export default RegisterHost;
myTabPage (BankCustomerRegister)
import React, { Component } from "react";
import {
Text,
View,
Image,
StyleSheet,
TextInput,
TouchableOpacity
} from "react-native";
import { TabNavigator } from "react-navigation";
import{StackNavigator} from 'react-navigation';
import FetchData from "../../utils/fetch.js";
class BankCustomerRegister extends Component {
constructor(props) {
super(props);
this.state = {
stCustId: "",
stIdcard: "",
stPhoneNum: "",
isMounted: false
};
}
}
};
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<Image source={require("../../resources/icons/bank.png")} />
<TextInput
style={styles.textInput}
onChangeText={this._handleCustId}
placeholderTextColor="black"
placeholder="Customer ID"
/>
<TextInput
style={styles.textInput}
placeholderTextColor="black"
onChangeText={this._handleIdCard}
placeholder="ID card"
/>
<TextInput
style={styles.textInput}
placeholderTextColor="black"
onChangeText={this._handlePhoneNum}
placeholder="Phone No"
/>
<TouchableOpacity
onPress={() => {
// NOTICE HERE
const navigateAction = NavigationActions.navigate({
routeName: "preactivate",
params: {},
});
this.props.navigation.dispatch(navigateAction);
}}
style={styles.touchable}
>
<Text style={styles.btnlabel}>Register</Text>
</TouchableOpacity>
</View>
);
}
}
export default BankCustomerRegister;
when i click touchable.its supposed to navigate to otherPage, i'ts not navigating anywhere , even no errors.
myOtherPage(preactivate)
import React, { Component } from "react";
import {
View,
Text,
StyleSheet
} from "react-native";
class PreUserActivation extends Component {
// Render callBack
render() {
return (
<View style={styles.container}>
<Text>Screen</Text>
</View>
);
}
}
export default PreUserActivation;
My router config in router.js
//tab Router
export const Tab = TabNavigator(
{
BankCustomerRegister: {
screen: BankCustomerRegister,
navigationOptions: {
tabBarLabel: "Bank Customer"
}
},
nonbankcustomer: {
screen: NonCustomerRegister,
navigationOptions: {
tabBarLabel: "New Customer"
}
}
},
{
tabBarPosition: "top",
animationEnabled: true,
tabBarOptions: {
// activeTintColor: "#e91e63",
labelStyle: {
fontSize: 16
},
style: {
backgroundColor: "#08AE9E"
},
tabStyle: { width: 200 } //Set width to make INLINE TABS
}
}
);
export const Root = StackNavigator({
board: {
screen: OnBoardScreen,
navigationOptions: {
header: null
}
},
preactivate: {
screen: PreUserActivation,
navigationOptions: {
header: null
}
},
Tabs: {
screen: Tab
}
});
Is there something i'm missing.

You need a reset. Use navigate() when navigating from one tab to another in the same TabNavigator for example. In your case, you are navigating to a screen in the parent navigator. Try this instead:
onPress={() => {
const navigateAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'preactivate'})
]
});
this.props.navigation.dispatch(navigateAction);
}}

Related

Switch navigator does not works in React Native

I've asked a question already, and modified as much as I can, but still in trouble.
Combined all children Screen js files into App.js
When I compile and run, App shows LoginScreen.js, not LoadingScreen.js.
Also, onPress={this.props.navigation.navigate('Loading')} does not works. If I press the button, it shows nothing.
What am I still missing?
import React from 'react'
import { StyleSheet, Platform, Image, Text, View, TextInput, Button, ActivityIndicator } from 'react-native'
import { createAppContainer, createSwitchNavigator } from 'react-navigation'
import { createBottomTabNavigator } from 'react-navigation-tabs';
import Ionicons from 'react-native-vector-icons/Ionicons';
class LoadingScreen extends React.Component {
render() {
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={this.props.navigation.navigate('Login')} />
</View>
)
}
}
class LoginScreen extends React.Component {
state = { email: '', password: '' }
render() {
return (
<View style={styles.logincontainer}>
<Button
title='Sign in' onPress={this.props.navigation.navigate('Loading')}
/>
<Button
title='Sign Up'
/>
</View>
)
}
}
const styles = StyleSheet.create({
loadingcontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
logincontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
logintextInput: {
height: 40,
width: '90%',
borderColor: 'gray',
borderWidth: 1,
marginTop: 8
},
})
const App = createSwitchNavigator(
{
Loading: {
screen: LoadingScreen,
},
Login: {
screen: LoginScreen,
},
}
);
export default createAppContainer(App);
Thank you for your help.
For just navigation, you can use a stack navigator. The switch navigator used for conditional rendering of two different stacks. Anyways you can set loading as the first screen buy setting initialRouteName to loading. Here is an example
createSwitchNavigator(
{
LimitedAccess: {
screen: Trial,
},
AppScreens: {
screen: AppScreens,
},
AuthScreens: {
screen: AuthScreens,
},
},
{
initialRouteName: signedIn ? 'AppScreens' : 'AuthScreens',
},
),
);
Note: Here signedIn is a conditional operator which decides the rendering of stacks.
The way your props are currently defined causes them to be instantly executed.
The onPress prop is instantly executed.
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={this.props.navigation.navigate('Login')} />
</View>
)
You should instead attach a function to onPress that can be executed when the button is pressed.
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={() => this.props.navigation.navigate('Login')} />
</View>
)
Your onPress-calls are running instantly, which causes your problems.
Change to:
import React from 'react'
import { StyleSheet, Platform, Image, Text, View, TextInput, Button, ActivityIndicator } from 'react-native'
import { createAppContainer, createSwitchNavigator } from 'react-navigation'
import { createBottomTabNavigator } from 'react-navigation-tabs';
import Ionicons from 'react-native-vector-icons/Ionicons';
class LoadingScreen extends React.Component {
render() {
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={() => this.props.navigation.navigate('Login')} />
</View>
)
}
}
class LoginScreen extends React.Component {
state = { email: '', password: '' }
render() {
return (
<View style={styles.logincontainer}>
<Button
title='Sign in' onPress={() => this.props.navigation.navigate('Loading')}
/>
<Button
title='Sign Up'
/>
</View>
)
}
}
const styles = StyleSheet.create({
loadingcontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
logincontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
logintextInput: {
height: 40,
width: '90%',
borderColor: 'gray',
borderWidth: 1,
marginTop: 8
},
})
const App = createSwitchNavigator(
{
Loading: {
screen: LoadingScreen,
},
Login: {
screen: LoginScreen,
},
}
);
export default createAppContainer(App);

Getting a Reference Error when starting my react native app

I am getting a reference Error message: can't find variable:error, i'm not able to figure out where I have written this variable in code. Someone help!!
This is my App.js (Starting point)
import React from 'react';
import Main from './components/MainComponent';
import { Provider } from 'react-redux';
import { ConfigureStore } from './redux/configureStore';
const store = ConfigureStore();
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<Main />
</Provider>
);
}
}
ActionTypes.js (This file represents different Actions which can be dispatched)
export const DISHES_LOADING = 'DISHES_LOADING';
export const ADD_DISHES = 'ADD_DISHES';
export const DISHES_FAILED = 'DISHES_FAILED';
export const ADD_COMMENTS = 'ADD_COMMENTS';
export const COMMENTS_FAILED = 'COMMENTS_FAILED';
export const PROMOS_LOADING = 'PROMOS_LOADING';
export const ADD_PROMOS = 'ADD_PROMOS';
export const PROMOS_FAILED = 'PROMOS_FAILED';
export const LEADERS_LOADING = 'LEADERS_LOADING';
export const ADD_LEADERS = 'ADD_LEADERS';
export const LEADERS_FAILED = 'LEADERS_FAILED';
ActionCreators.js (This file fetches data from a fake Rest api and performs the necessary computations dispatches the data and action accordingly )
import {createStore, combineReducers, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import { dishes } from './dishes';
import { comments } from './comments';
import { promotions } from './promotions';
import { leaders } from './leaders';
export const ConfigureStore = () => {
const store = createStore(
combineReducers({
dishes,
comments,
promotions,
leaders
}),
applyMiddleware(thunk, logger)
);
return store;
}
AboutComponent.js (This is one of my component)
import React, {Component} from 'react';
import { Text, ScrollView } from 'react-native';
import { Card } from 'react-native-elements';
import { FlatList } from 'react-native';
import { ListItem } from 'react-native-elements';
import { connect } from 'react-redux';
import { baseUrl } from '../shared/baseUrl';
import { Loading } from './LoadingComponent';
const mapStateToProps = state => {
return {
leaders: state.leaders
}
}
function History() {
return(
<Card title="Our History">
<Text style={{margin: 10}}>
Started in 2010, Ristorante con Fusion quickly established itself as a culinary icon par excellence in Hong Kong. With its unique brand of world fusion cuisine that can be found nowhere else, it enjoys patronage from the A-list clientele in Hong Kong. Featuring four of the best three-star Michelin chefs in the world, you never know what will arrive on your plate the next time you visit us.{"\n\n"}
The restaurant traces its humble beginnings to The Frying Pan, a successful chain started by our CEO, Mr. Peter Pan, that featured for the first time the world's best cuisines in a pan.
</Text>
</Card>
);
}
function RenderLeaders(props) {
const leaders = props.leaders;
const renderLeaderItems = ({item, index}) => {
return (
<ListItem
key={index}
title={item.name}
subtitle={item.description}
hideChevron={true}
leftAvatar={{source: {uri: baseUrl + item.image}}}
/>
);
};
return (
<Card title='Comments' >
<FlatList
data={leaders}
renderItem={renderLeaderItems}
keyExtractor={item => item.id.toString()}
/>
</Card>
);
}
class About extends Component {
static navigationOptions = {
title: 'About Us'
};
render(){
if (this.props.leaders.isLoading) {
return(
<ScrollView>
<History />
<Card
title='Corporate Leadership'>
<Loading />
</Card>
</ScrollView>
);
}
else if (this.props.leaders.errMess) {
return(
<ScrollView>
<History />
<Card
title='Corporate Leadership'>
<Text>{this.props.leaders.errMess}</Text>
</Card>
</ScrollView>
);
}
else{
return (
<ScrollView>
<History/>
<RenderLeaders leaders={this.props.leaders.leaders} />
</ScrollView>
)
}
}
}
export default connect(mapStateToProps)(About);
MainComponent.js (The file which controls the side drawer and navigation)
import React, {Component } from 'react';
import Menu from './MenuComponent';
import DishDetail from './DishdetailComponent';
import { View, Platform, Image, StyleSheet, ScrollView, Text } from 'react-native';
import {createStackNavigator} from 'react-navigation-stack';
import { createAppContainer, SafeAreaView } from 'react-navigation';
import { createDrawerNavigator, DrawerItems } from 'react-navigation-drawer';
import Home from './HomeComponent';
import Contact from './ContactComponent';
import About from './AboutComponent';
import {Icon} from 'react-native-elements';
import { connect } from 'react-redux';
import { fetchDishes, fetchComments, fetchPromos, fetchLeaders } from '../redux/ActionCreators';
const mapStateToProps = state => {
return {
}
}
const mapDispatchToProps = dispatch => ({
fetchDishes: () => dispatch(fetchDishes()),
fetchComments: () => dispatch(fetchComments()),
fetchPromos: () => dispatch(fetchPromos()),
fetchLeaders: () => dispatch(fetchLeaders()),
})
const MenuNavigator = createStackNavigator({
Menu:{screen:Menu,
navigationOptions:({navigation}) => ({
headerLeft: <Icon name='menu' size={24} color='white'
onPress={()=>navigation.toggleDrawer()}
/>
})},
DishDetail: { screen: DishDetail }
}, {
initialRouteName: 'Menu',
navigationOptions: {
headerStyle: {
backgroundColor: "#512DA8"
},
headerTintColor: '#fff',
headerTitleStyle: {
color: "#fff"
}
}
});
const HomeNavigator = createStackNavigator({
Home: { screen: Home }
}, {
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: "#512DA8"
},
headerTitleStyle: {
color: "#fff"
},
headerTintColor: "#fff",
headerLeft: <Icon name='menu' size={24} color='white'
onPress={()=>navigation.toggleDrawer()}
/>
})
});
const AboutNavigator = createStackNavigator({
Home: { screen: About }
}, {
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: "#512DA8"
},
headerTitleStyle: {
color: "#fff"
},
headerTintColor: "#fff",
headerLeft: <Icon name='menu' size={24} color='white'
onPress={()=>navigation.toggleDrawer()}
/>
})
});
const ContactNavigator = createStackNavigator({
Home: { screen: Contact }
}, {
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: "#512DA8"
},
headerTitleStyle: {
color: "#fff"
},
headerTintColor: "#fff",
headerLeft: <Icon name='menu' size={24} color='white'
onPress={()=>navigation.toggleDrawer()}
/>
})
});
const CustomDrawerContentComponent = (props) => (
<ScrollView>
<SafeAreaView style={styles.container} forceInset={{ top: 'always', horizontal: 'never' }}>
<View style={styles.drawerHeader}>
<View style={{flex:1}}>
<Image source={require('./images/logo.png')} style={styles.drawerImage} />
</View>
<View style={{flex: 2}}>
<Text style={styles.drawerHeaderText}>Ristorante Con Fusion</Text>
</View>
</View>
<DrawerItems {...props} />
</SafeAreaView>
</ScrollView>
);
const MainNavigator = createDrawerNavigator({
Home:
{ screen: HomeNavigator,
navigationOptions: {
title: 'Home',
drawerLabel: 'Home',
drawerIcon: ({tintColor}) => (
<Icon
name='home'
type='font-awesome'
size={24}
color={tintColor}
/>
)
}
},
About:
{ screen: AboutNavigator,
navigationOptions: {
title: 'About Us',
drawerLabel: 'About Us',
drawerIcon: ({tintColor}) => (
<Icon
name='info-circle'
type='font-awesome'
size={24}
color={tintColor}
/>
)
}
},
Menu:
{ screen: MenuNavigator,
navigationOptions: {
title: 'Menu',
drawerLabel: 'Menu',
drawerIcon: ({tintColor}) => (
<Icon
name='list'
type='font-awesome'
size={24}
color={tintColor}
/>
)
},
},
Contact:{
screen:ContactNavigator,
navigationOptions: {
title: 'Contact Us',
drawerLabel: 'Contact Us',
drawerIcon: ({tintColor}) => (
<Icon
name='address-card'
type='font-awesome'
size={22}
color={tintColor}
/>
)
}
}
}, {
drawerBackgroundColor: '#D1C4E9',
contentComponent: CustomDrawerContentComponent
});
const App = createAppContainer(MainNavigator);
class Main extends Component {
componentDidMount() {
this.props.fetchDishes();
this.props.fetchComments();
this.props.fetchPromos();
this.props.fetchLeaders();
}
onDishSelect(dishId) {
this.setState({selectedDish: dishId})
}
render() {
return (
<View style={{flex:1, paddingTop: Platform.OS === 'ios' ? 0 : Expo.Constants.statusBarHeight }}>
<App />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
drawerHeader: {
backgroundColor: '#512DA8',
height: 140,
alignItems: 'center',
justifyContent: 'center',
flex: 1,
flexDirection: 'row'
},
drawerHeaderText: {
color: 'white',
fontSize: 24,
fontWeight: 'bold'
},
drawerImage: {
margin: 10,
width: 80,
height: 60
}
});
export default connect(mapStateToProps, mapDispatchToProps)(Main);

React native createDrawerNavigator is not working

Could you please help me on this small issue.
I am very very new to React native and here i am training in learn react navigation. My problem is Drawer navigator is not working when i try to swap from left to right. But bottom navigator is working. Any idea whats wrong with this please.
Also: if you can please send me a good sample to learn this area.
I have some samples, but most of the samples are outdated.
MyCode:
import React from 'react';
import {TouchableOpacity, View, Text, Image} from 'react-native';
import {createAppContainer, createSwitchNavigator} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import {createBottomTabNavigator} from 'react-navigation-tabs';
import {createDrawerNavigator} from 'react-navigation-drawer';
import HomeScreen2 from '../screens/HomeScreen2';
import HomeScreen from '../screens/HomeScreen';
import Setup from '../screens/Setup';
const HomeStack = createStackNavigator(
{
//Defination of Navigaton from home screen
Home: { screen: HomeScreen },
// Details: { screen: ProfileScreen },
},
{
defaultNavigationOptions: {
//Header customization of the perticular Screen
headerStyle: {
backgroundColor: '#42f44b',
},
headerTintColor: '#FFFFFF',
title: 'Home',
//Header title
},
}
);
const SettingsStack = createStackNavigator(
{
//Defination of Navigaton from setting screen
Settings: { screen: Setup },
},
{
defaultNavigationOptions: {
//Header customization of the perticular Screen
headerStyle: {
backgroundColor: '#42f44b',
},
headerTintColor: '#FFFFFF',
title: 'Settings',
//Header title
},
}
);
const TabMain = createBottomTabNavigator(
{
TAB1: HomeStack,
TAB2: SettingsStack,
},
{
initialRouteName: 'TAB1',
}
)
const DrawHomeView = createStackNavigator({
HomeV: {screen: HomeScreen2}},
{
headerMode: 'float',
navigationOptions: ({navigation}) => ({
headerStyle: {
backgroundColor: 'rgb(255,45,85)',
paddingLeft: 10,
paddingRight: 10
},
title: 'Map View',
headerTintColor: 'white',
headerLeft: <View>
<TouchableOpacity
onPress={() => {
if (navigation.state.isDrawerOpen === false) {
navigation.dispatch(DrawerActions.openDrawer());
} else {
navigation.dispatch(DrawerActions.closeDrawer());
}
}}>
<Text>Menu</Text>
</TouchableOpacity>
</View>
})
});
const DrawSettingsView = createStackNavigator({
SettingsV: {screen: Setup}},
{
headerMode: 'float',
navigationOptions: ({navigation}) => ({
headerStyle: {
backgroundColor: 'rgb(255,45,85)',
paddingLeft: 10,
paddingRight: 10
},
title: 'Map View',
headerTintColor: 'white',
headerLeft: <View>
<TouchableOpacity
onPress={() => {
if (navigation.state.isDrawerOpen === false) {
navigation.dispatch(DrawerActions.openDrawer());
} else {
navigation.dispatch(DrawerActions.closeDrawer());
}
}}>
<Text>Menu</Text>
</TouchableOpacity>
</View>
})
});
const TabMain2 = createDrawerNavigator(
{
TAB3: DrawHomeView,
TAB4: DrawSettingsView,
},
{
initialRouteName: 'TAB3',
}
)
export default createAppContainer(createSwitchNavigator(
{
Sub1: TabMain,
Sub2: TabMain2,
},
{
initialRouteName: 'Sub2',
}
));
Okay. After some dabbling with your code and the docs : https://reactnavigation.org/docs/nesting-navigators/
and please read the docs and try their examples as they are excellent descriptive and available for real time execution on snack.
For the second part of the question, i put together an example for you:
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
//Import necessary components
//Create Screens, Dummy screens in this case.
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
function Feed ({ navigation, route }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{fontSize: 40}}>Feed </Text>
</View>
);}
function Home ({ navigation, route }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{fontSize: 40}}> Home </Text>
</View>
);}
// Here is your questions answer, just create a Bottom Navigator
// and a Drawer Navigator and nest them in each other after declaring your
// screens.
const Tab = createBottomTabNavigator();
const Drawer = createDrawerNavigator();
function HomeScreen({ navigation }) {
return (
<Tab.Navigator>
//Put your Tab screens here.
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Feed" component={Feed} />
</Tab.Navigator>
);
}
export default function App() {
return (
// For the main export create a navigation container and declare the
// Drawer Navigator inside the main navigation container, then use that to
// To Access your Tab navigator "HomeScreen" and put whatever else you
// Want in your Drawer Navigator.
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
Explanation: You are only allowed to nest navigators within each other and not within the main navigation container.
This code has been tested using expo-cli 3.18.4

React Native Navigation with React Native Admob About

I created a 3 page application with React native navigation. Admob ads are on the 3rd page. I want to try the same ad code on all three screens. If there is any idea in this matter, please share. Thank you.
For better understanding I give the following expo code.
import React, { Component } from 'react';
import {
WebView,
AppRegistry,
StyleSheet,
Text,
View,
Button,
Alert
} from 'react-native';
import { StackNavigator } from 'react-navigation';
import ListComponent from './ListComponent';
class App extends Component {
static navigationOptions = {
title: 'App',
};
OpenSecondActivityFunction = () => {
this.props.navigation.navigate('Second');
};
render() {
return (
<View style={styles.container}>
<Button
onPress={this.OpenSecondActivityFunction}
title="Open Second Activity"
/>
</View>
);
}
}
class SecondActivity extends Component {
static navigationOptions = {
title: 'SecondActivity',
};
OpenThirdActivityFunction = data => {
this.props.navigation.navigate('Third');
};
render() {
return (
<View style={{ flex: 1 }}>
<ListComponent
OpenThirdActivityFunction={this.OpenThirdActivityFunction}
/>
</View>
);
}
}
class ThirdActivity extends Component {
static navigationOptions = {
title: 'ThirdSecondActivity',
};
render() {
return (
<View style={{ flex: 1 }}>
<Text>3</Text>
</View>
);
}
}
const ActivityProject = StackNavigator({
First: { screen: App },
Second: { screen: SecondActivity },
Third: { screen: ThirdActivity },
});
export default ActivityProject;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
});
Listcomponent.js
import React, { Component } from 'react';
import {
AppRegistry,
View,
Text,
FlatList,
ActivityIndicator,
} from 'react-native';
import { List, ListItem, SearchBar } from 'react-native-elements';
class ListComponents extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
page: 1,
seed: 1,
error: null,
refreshing: false,
};
}
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: '98%',
backgroundColor: '#CED0CE',
marginLeft: '2%',
}}
/>
);
};
renderHeader = () => {
return <SearchBar placeholder="Type Here..." lightTheme round />;
};
renderFooter = () => {
if (!this.state.loading) return null;
return (
<View
style={{
paddingVertical: 20,
borderTopWidth: 1,
borderColor: '#CED0CE',
}}>
<ActivityIndicator animating size="large" />
</View>
);
};
render() {
return (
<List containerStyle={{ borderTopWidth: 0, borderBottomWidth: 0 }}>
<FlatList
data={[{ name: 1, coders: 2 }]}
renderItem={({ item }) => (
<ListItem
roundAvatar
title={`${item.name}`}
subtitle={item.coders}
containerStyle={{ borderBottomWidth: 0 }}
onPress={() => this.props.OpenThirdActivityFunction(item.coders)}
/>
)}
keyExtractor={item => item.coders}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
/>
</List>
);
}
}
export default ListComponents;

React Native: setState triggers unwanted Tab change in Tab Navigator

Something does not make sense with my code.
I am using React Native to create a app.
In that app I am using a Tab Navigator.
It works fine until I call this.setState which for some reason triggers a unwanted Tab change from one tab to the other.
Why would setState trigger a Tab change??
This is my code:
import React from 'react';
import { StyleSheet, Text, View, FlatList, TextInput, StatusBar, Button } from 'react-native';
import { TabNavigator } from 'react-navigation';
import { Constants } from 'expo'
import { purple, white } from './utils/colors'
const R = require('ramda')
function CustomStatusBar({ backgroundColor, ...props }){
return (
<View style={{backgroundColor, height: Constants.statusBarHeight}}>
<StatusBar translucent backgroundColor={backgroundColor} {...props} />
</View>
)
}
export default class App extends React.Component {
constructor(props){
super(props)
this.handleDeckTitle = this.handleDeckTitle.bind(this)
}
state = {
title: ''
}
renderItem = (sample) => {
console.log('renderItem', sample)
return <Text>SAMPLE DATA</Text>
}
handleDeckTitle(e){
console.log('handleDeckTitle')
console.log('e', e)
console.log('this.state', this.state)
this.setState((prevState, props) => ({
title: e
}));
}
submitDeckTitle(){
console.log('submitDeckTitle')
}
render() {
console.log('R', R)
const Decks = () => {
return (
<View>
<CustomStatusBar backgroundColor={purple} barStyle='light-content' />
<Text>Decks!</Text>
</View>
)
}
const NewDeck = () => {
return (
<View>
<CustomStatusBar backgroundColor={purple} barStyle='light-content' />
<Text>What is the title of your new deck?</Text>
<TextInput style = {styles.input} onChangeText={this.handleDeckTitle}/>
<Button onPress={this.submitDeckTitle} title="Submit" />
</View>
)
}
const Tabs = TabNavigator({
Decks: {
screen: Decks
},
'New Deck': {
screen: NewDeck
},
});
return (
<Tabs />
);
}
}
const styles = StyleSheet.create({
container: {
paddingTop: 23,
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
input: {
margin: 15,
height: 40,
borderColor: '#7a42f4',
borderWidth: 1
},
});
I don't see what is wrong with this code.
In fact I think it should just work normally but it does not.
It triggers a tab change when I call handleDeckTitle which then calls this.setState
Got it to work now.
I changed the part that calls setState to be be a Separate Component with its own state.
Here is the code:
import React from 'react';
import { StyleSheet, Text, View, FlatList, TextInput, StatusBar, Button } from 'react-native';
import { TabNavigator } from 'react-navigation';
import { Constants } from 'expo'
import { purple, white } from './utils/colors'
const R = require('ramda')
function CustomStatusBar({ backgroundColor, ...props }){
return (
<View style={{backgroundColor, height: Constants.statusBarHeight}}>
<StatusBar translucent backgroundColor={backgroundColor} {...props} />
</View>
)
}
const Decks = () => {
return (
<View>
<CustomStatusBar backgroundColor={purple} barStyle='light-content' />
<Text>Decks!</Text>
</View>
)
}
class NewDeck extends React.Component {
constructor(props){
super(props)
this.handleDeckTitle = this.handleDeckTitle.bind(this)
}
state = {
title: ''
}
handleDeckTitle(e){
console.log('handleDeckTitle')
console.log('e', e)
console.log('this.state', this.state)
this.setState((prevState, props) => ({
title: e
}));
}
render(){
return (
<View>
<CustomStatusBar backgroundColor={purple} barStyle='light-content' />
<Text>What is the title of your new deck?</Text>
<TextInput style = {styles.input} onChangeText={this.handleDeckTitle}/>
<Button onPress={this.submitDeckTitle} title="Submit" />
</View>
)
}
}
const Tabs = TabNavigator({
Decks: {
screen: Decks
},
'New Deck': {
screen: NewDeck
},
});
export default class App extends React.Component {
constructor(props){
super(props)
// this.handleDeckTitle = this.handleDeckTitle.bind(this)
}
state = {
title: ''
}
renderItem = (sample) => {
console.log('renderItem', sample)
return <Text>SAMPLE DATA</Text>
}
submitDeckTitle(){
console.log('submitDeckTitle')
}
render() {
console.log('R', R)
return (
<Tabs />
);
}
}
const styles = StyleSheet.create({
container: {
paddingTop: 23,
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
input: {
margin: 15,
height: 40,
borderColor: '#7a42f4',
borderWidth: 1
},
});

Resources