state params undefined using react-navigation - react-native

I can navigate to a screen but params are undefined, state is just:
{
key: "id-1574950261181-7",
routeName: "Video Player"
}
Navigate from:
render() {
const {
id,
title,
description,
video,
preview,
push,
dispatch,
testLink,
navigate
} = this.props;
return (
<TouchableHighlight
style={styles.episode}
activeOpacity={1}
underlayColor="#808080"
onPress={() => {
navigate("VideoPlayer", { tester: id });
}}
>
<View style={styles.title}>
<Text style={styles.text}>{title}</Text>
</View>
</TouchableHighlight>
);
}
My VideoPlayerScreen (for brevity) gives me :
import React from "react";
import {
...
} from "react-native";
...
...
class VideoPlayerScreen extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.onShare = this.onShare.bind(this);
this.navigateScreen = this.navigateScreen.bind(this);
this.bookmarkVideo = this.bookmarkVideo.bind(this);
this.loadRecapVideo = this.loadRecapVideo.bind(this);
}
....
render() {
const {
videos,
bookmarkVideo,
navigate,
state: {
params: { id }
}
} = this.props;
console.log(this.props.navigation.state.params);
let videoProps = videos.find(obj => obj.id == id);
return (<View />)
}
}
const mapDispatchToProps = dispatch => ({
bookmarkVideo: id => dispatch(bookmarkVideo(id))
});
const mapStateToProps = state => {
return {
videos: state.tcApp.videos
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(VideoPlayerScreen);

In case you are using react-native-navigation 4x you should change the props variable
from:
const {
...
navigate,
} = this.props;
to:
const {
...
navigation,
} = this.props;
and call it like:
onPress={() => {
navigation.navigate("VideoPlayer", { tester: id });
}}
Official Doc: React Native Navigation Docs
Friendly.

Related

Cannot update a component (`ForwardRef(BaseNavigationContainer)`) while rendering a different component (`Signinscreen`)

I am getting the following warning:
Warning: Cannot update a component (ForwardRef(BaseNavigationContainer)) while rendering a different component (Signinscreen). To locate the bad setState() call inside Signinscreen, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
Signinscreen.js
import React, { Component, useEffect } from 'react'
import { View, Text, TextInput, Image } from 'react-native'
// STYLE
import styles from "./style"
// FORMIK
import { Formik } from 'formik'
// COMPONENT
import Navigationcomponent from "../../assets/components/navigationcomponent"
// STORAGE
import AsyncStorage from '#react-native-async-storage/async-storage'
// REDUX
import { connect } from 'react-redux'
// REDUX ACTION
import { initialaccount,user_signin } from '../../actions/index'
// YUP
import * as yup from 'yup'
// IMAGE
const mainimage = require("../../assets/images/mainlogo.png")
// SCREEN
import Homescreen from "../homescreen";
const SigninSchema = yup.object().shape({
username: yup
.string()
.min(6)
.max(12)
.required('Please, provide your username!')
.nullable(),
password: yup
.string()
.min(6)
.required('Please, provide your password!')
.nullable(),
})
const Signinscreen = ({navigation, initialaccount_d, user_signin_d, user_s}) => {
const storeData = async (values) => {
try {
// await AsyncStorage.setItem('me', JSON.stringify(values))
// await initialaccount_d(true)
// console.log(values)
await user_signin_d(values)
//
// navigation.navigate("Initialhomescreen")
} catch (e) {
// saving error
}
}
const validatecheck = () => {
AsyncStorage.setItem('me', JSON.stringify(user_s.usersignin_success))
navigation.navigate("Initialhomescreen")
// console.log(user_s.usersignin_success)
// if (user_s.usersignin_success != null) {
// // console.log(user_s.usersignin_success)
// // navigation.navigate("Initialhomescreen")
// if (user_s.usersignin_success.status == 200) {
// // console.log("user_s.usersignin_success")
// await AsyncStorage.setItem('me', JSON.stringify(user_s.usersignin_success))
// navigation.navigate("Initialhomescreen")
// }
// }
}
// ONBACK PRESS
useEffect(() => {
// validatecheck()
navigation.addListener('beforeRemove', e => {
// REMOVE INPUT VALUE BEFORE LEAVE SCREEN
user_signin_d(null)
});
},[])
if (user_s.usersignin_success != null && user_s.usersignin_success.status == 200) {
// validatecheck()
return(
<View>
{validatecheck()}
<Text>Load...</Text>
</View>
)
} else {
return(
<Formik
// validationSchema={SigninSchema}
initialValues={{ username: null, password: null}}
onSubmit={values => storeData(values)}>
{({ handleChange, handleSubmit, values, errors, touched }) =>
(
<View style={styles.main}>
<View style={styles.mainconf}>
<Image style={styles.imageconf} source={mainimage}></Image>
<View style={styles.inputconfmain}>
<Text style={styles.titleconf}>
Create now, for ever...
</Text>
<TextInput
style={styles.inputconf}
placeholder="username"
placeholderTextColor="gray"
onChangeText={handleChange('username')}
value={values.username}>
</TextInput>
{touched.username && errors.username &&
<Text style={{ fontSize: 12, color: 'red', alignSelf: "center" }}>{errors.username}</Text>
}
<TextInput
style={styles.inputconf}
placeholder="password"
placeholderTextColor="gray"
secureTextEntry={true}
onChangeText={handleChange('password')}
value={values.password}>
</TextInput>
{touched.password && errors.password &&
<Text style={{ fontSize: 12, color: 'red', alignSelf: "center" }}>{errors.password}</Text>
}
<Text onPress={handleSubmit} style={styles.btnsignupconf}>
Sign in
</Text>
{user_s.usersignin_success != null ? (user_s.usersignin_success.status == 400 ? <Text style={styles.warningmsg}>{user_s.usersignin_success.message}</Text> : (null)) : null}
</View>
</View>
</View>
)}
</Formik>
)
}
}
const mapStateToProps = (state) => ({
user_s: state.user
})
const mapDispatchToProps = (dispatch) => ({
initialaccount_d: (value) => dispatch(initialaccount(value)),
user_signin_d: (value) => dispatch(user_signin(value))
})
export default connect(mapStateToProps, mapDispatchToProps)(Signinscreen)
Homescreen.js
import React, { Component, useEffect, useState } from 'react'
import { View, Text, Image, SafeAreaView, BackHandler } from 'react-native'
// COMPONENT
import Navigationcomponent from "../../assets/components/navigationcomponent";
// STORAGE
import AsyncStorage from '#react-native-async-storage/async-storage';
// STYLE
import styles from "./style"
// REDUX
import { connect } from 'react-redux'
// REDUX ACTION
import { initialaccount } from '../../actions/index'
const Homescreen = ({navigation, initialaccount_s, initialaccount_d, user_s}) => {
// useEffect(() => {
// myaccount()
// }, []);
// myaccount = async () => {
// try {
// const value = await AsyncStorage.getItem('me')
// if(value !== null) {
// // value previously stored
// console.log('Yay!! you have account.')
// // await navigation.navigate("Homescreen")
// await initialaccount_d(true)
// } else {
// console.log('Upss you have no account.')
// // await navigation.navigate("Welcomescreen")
// await initialaccount_d(false)
// }
// } catch(e) {
// // error reading value
// }
// }
// Call back function when back button is pressed
const backActionHandler = () => {
BackHandler.exitApp()
return true;
}
useEffect(() => {
console.log(user_s.usersignin_success)
// Add event listener for hardware back button press on Android
BackHandler.addEventListener("hardwareBackPress", backActionHandler);
return () =>
// clear/remove event listener
BackHandler.removeEventListener("hardwareBackPress", backActionHandler);
},[])
// const validatecheck = () => {
// console.log(user_s.usersignin_success)
// // if (user_s.usersignin_success == null || user_s.usersignin_success.status == 400) {
// // navigation.navigate("Signinscreen")
// // }
// }
clearAll = async () => {
try {
await AsyncStorage.clear()
await initialaccount_d(false)
navigation.navigate("Initialscreen")
console.log('Done. cleared')
} catch(e) {
console.log('Upss you have no account.')
}
}
const getData = async () => {
try {
const value = await AsyncStorage.getItem('me')
if(value !== null) {
// value previously stored
console.log(value)
} else {
console.log('Upss you have no account.')
}
} catch(e) {
// error reading value
}
}
return(
<View style={styles.main}>
<View style={styles.logoutconf}>
<Text onPress={() => clearAll()}>LOGOUT</Text>
<Text onPress={() => getData()}>cek data</Text>
</View>
<Navigationcomponent style={styles.mainconf} />
</View>
)
}
const mapStateToProps = (state) => ({
initialaccount_s: state.user,
user_s: state.user
})
const mapDispatchToProps = (dispatch) => ({
initialaccount_d: (value) => dispatch(initialaccount(value))
})
export default connect(mapStateToProps, mapDispatchToProps)(Homescreen)
I encountered the same problem and I think that passing navigation.navigate("<screen_name>");} to another screen's onPress() prop (like
onPress={() => {navigation.navigate("<screen_name>");}
or
...
const navFunction = () => {
navigation.navigate("<screen_name>");
};
return(
<TouchableOpactiy onPress={() => {navFunction();} />
...
</TouchableOpacity>
);
...
).
I solved this by not passing the navigation from the onPress prop in the homeScreen and instead using the navigation prop inherent to the otherScreen.
// The homescreen.
const App = props => {
return(
<TouchableOpactiy
onPress={() => {
props.navigation.navigate('OtherScreen');
}}
>...</TouchableOpacity>
);
};
// The other screen.
const App = ({navigation}) => {
return(
<TouchableOpacity
onPress={() => {
navigation.navigate('HomeScreen');
}}
>...</TouchableOpacity>
);
};

React Native WebView App not exit on pressing back button

React Native WebView App not exit on pressing back button after setting Go back functionality on back button pressed. I want go back functionality on pressing back button when webview is not on home page and when webview is on home page then exit the app.
export default class WebView extends Component {
constructor (props) {
super(props);
this.WEBVIEW_REF = React.createRef();
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
handleBackButton = ()=>{
this.WEBVIEW_REF.current.goBack();
return true;
}
onNavigationStateChange(navState) {
this.setState({
canGoBack: navState.canGoBack
});
}
render(){
return (
<WebView
source={{ uri: 'https://stackoverflow.com' }}
ref={this.WEBVIEW_REF}
onNavigationStateChange={this.onNavigationStateChange.bind(this)}
/>
);
}
}
Since you are managing the state of canGoBack inside onNavigationStateChange function, Change your handleBackButton function as below,
handleBackButton = () => {
if (this.state.canGoBack) {
this.WEBVIEW_REF.current.goBack();
return true;
}
}
Check below complete example
import React, { Component } from "react";
import { BackHandler } from "react-native";
import { WebView } from "react-native-webview";
export default class App extends Component {
WEBVIEW_REF = React.createRef();
state = {
canGoBack: false,
};
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.handleBackButton);
}
handleBackButton = () => {
if (this.state.canGoBack) {
this.WEBVIEW_REF.current.goBack();
return true;
}
};
onNavigationStateChange = (navState) => {
this.setState({
canGoBack: navState.canGoBack,
});
};
render() {
return (
<WebView
source={{ uri: "https://stackoverflow.com" }}
ref={this.WEBVIEW_REF}
onNavigationStateChange={this.onNavigationStateChange}
/>
);
}
}
Hope this helps you. Feel free for doubts.
I had this problem for quite a while but i have managed to resolve it. Problem that I experienced was that goBack (which is used as back event) function was triggered before onNavigationStateChange but somehow state was change although goBack function was called first.
const HomeScreen = () => {
const {web} = config;
const ref = useRef();
const [canGoBack, setCanGoBack] = useState(false);
const setupState = event => {
setCanGoBack(event?.canGoBack);
};
useEffect(() => {
const goBack = () => {
if (canGoBack === false) {
Alert.alert(
'Exit App',
'Do you want to exit app?',
[
{text: 'No', onPress: () => console.log('No'), style: 'cancel'},
{text: 'Yes', onPress: () => BackHandler?.exitApp()},
],
{cancelable: false},
);
}
ref?.current?.goBack();
return true;
};
BackHandler?.addEventListener('hardwareBackPress', () => goBack());
return () =>
BackHandler?.removeEventListener('hardwareBackPress', () => goBack());
}, [canGoBack]);
return (
<View style={styles.mainContainer}>
{/* last version 11.21.1 */}
<WebView
ref={ref}
source={{uri: web?.url}}
style={{flex: 1}}
cacheEnabled={web.cacheEnabled}
automaticallyAdjustContentInsets={false}
domStorageEnabled={true}
startInLoadingState={true}
allowsInlineMediaPlayback={true}
allowsBackForwardNavigationGestures
onNavigationStateChange={e => setupState(e)}
/>
</View>
);
};
export default HomeScreen;

how to show Loader till API get data using redux?

I am new to react and redux. I have implemented API fetching using redux but not sure where should i put code for loader till API gives data and error message if no network or API fails.
everything is working fine I am getting data too..only thing i stick is how to show activity indicator and error message. Is there any way to do that? Thanks in advance :)
reducer.js
export const GET_REPOS = 'my-awesome-app/repos/LOAD';
export const GET_REPOS_SUCCESS = 'my-awesome-app/repos/LOAD_SUCCESS';
export const GET_REPOS_FAIL = 'my-awesome-app/repos/LOAD_FAIL';
const initialState = {
repos: [],
loading: false,
error: null
};
export default function reducer(state = initialState , action) {
switch (action.type) {
case GET_REPOS:
return { ...state, loading: true };
case GET_REPOS_SUCCESS:
return { ...state, loading: false, repos: action.payload.data };
case GET_REPOS_FAIL:
return {
...state,
loading: false,
error: 'Error while fetching repositories',
};
default:
return state;
}
}
export function listRepos(photos) {
return {
type: GET_REPOS,
payload: {
request: {
url: `photos/`
}
}
};
}
export function listThumb(albumId) {
return {
type: GET_REPOS,
payload: {
request: {
url: `photos?albumId=${albumId}`
}
}
};
}
home.js
import React, { Component } from 'react';
import { ActivityIndicator } from 'react-native-paper';
import { View, Text, FlatList, StyleSheet, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';
import styles from '../HomeComponent/style';
import { Ionicons } from '#expo/vector-icons';
import { listRepos } from '../../../reducer';
class Home extends Component {
componentDidMount() {
this.props.dispatch(fetchProducts());
this.props.listRepos('');
}
FlatListItemSeparator = () => (
<View style={styles.flatListItemSeparator} />
)
renderItem = ({ item }) => (
<View style={styles.listRowContainer}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('ThumbnailViewScreen', {
albumID: item.id,
})} style={styles.listRow}>
<View style={styles.listTextNavVIew}>
<Text style={styles.albumTitle}> {item.title} </Text>
<Ionicons name='md-arrow-dropright' style={styles.detailArrow} />
</View>
</TouchableOpacity>
</View>
);
render() {
const { error, loading, products } = this.props;
if (error) {
return <Text>adadf </Text>;
}
if (loading) {
return (
<View style={{ flex: 1, paddingTop: 30 }}>
<ActivityIndicator animating={true} size='large' />
</View>
);
}
const { repos } = this.props;
return (
<View style={styles.MainContainer} >
<FlatList
styles={styles.container}
data={repos}
renderItem={this.renderItem}
ItemSeparatorComponent={this.FlatListItemSeparator}
/>
</View>
);
}
}
const mapStateToProps = state => {
let storedRepositories = state.repos.map(repo => ({ key: repo.id, ...repo }));
return {
repos: storedRepositories
};
};
const mapDispatchToProps = {
listRepos
};
export default connect(mapStateToProps, mapDispatchToProps)(Home);
const mapStateToProps = state => {
let storedRepositories = state.repos.map(repo => ({ key: repo.id, ...repo }));
return {
repos: storedRepositories
};
};
loading may not have been passed as a prop to Home. To fix that,
add it to mapStateToProps:
return {
repos: storedRepositories,
loading: state.loading
};

Update props from other component in react native

I have a Main class which I show an array to user, then in detail page user can edit each element which I'm passing using react navigation parameter. I want to edit my array in the detail class and save it using async storage.
//Main.jsimport React from 'react';
import {
StyleSheet ,
Text,
View,
TextInput,
ScrollView,
TouchableOpacity,
KeyboardAvoidingView,
AsyncStorage
} from 'react-native'
import Note from './Note'
import detail from './Details'
import { createStackNavigator, createAppContainer } from "react-navigation";
export default class Main extends React.Component {
static navigationOptions = {
title: 'To do list',
headerStyle: {
backgroundColor: '#f4511e',
},
};
constructor(props){
super(props);
this.state = {
noteArray: [],
noteText: '',
dueDate: ''
};
}
async saveUserTasks(value) {
try {
await AsyncStorage.setItem('#MySuperStore:userTask',JSON.stringify(value));
} catch (error) {
console.log("Error saving data" + error);
}
}
getUserTasks = async() =>{
try {
const value = await AsyncStorage.getItem('#MySuperStore:userTask');
if (value !== null){
this.setState({ noteArray: JSON.parse(value)});
}
} catch (error) {
console.log("Error retrieving data" + error);
}
}
render() {
this.getUserTasks()
let notes = this.state.noteArray.map((val,key) => {
return <Note key={key} keyval={key} val={val}
deleteMethod={ () => this.deleteNote(key)}
goToDetailPage= {() => this.goToNoteDetail(key)}
/>
});
const { navigation } = this.props;
return(
<KeyboardAvoidingView behavior='padding' style={styles.keyboard}>
<View style={styles.container}>
<ScrollView style={styles.scrollContainer}>
{notes}
</ScrollView>
<View style={styles.footer}>
<TextInput
onChangeText={(noteText) => this.setState({noteText})}
style={styles.textInput}
placeholder='What is your next Task?'
placeholderTextColor='white'
underlineColorAndroid = 'transparent'
>
</TextInput>
</View>
<TouchableOpacity onPress={this.addNote.bind(this)} style={styles.addButton}>
<Text style={styles.addButtonText}> + </Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
);
}
addNote(){
if (this.state.noteText){
var d = new Date();
this.state.noteArray.push({
'creationDate': d.getFullYear() + "/" + (d.getMonth()+1) + "/" + d.getDay(), 'taskName': this.state.noteText,'dueDate':'YYYY/MM/DD'
});
this.setState({noteArray:this.state.noteArray})
this.setState({noteText: ''});
this.saveUserTasks(this.state.noteArray)
}
}
deleteNote(key){
this.state.noteArray.splice(key,1);
this.setState({noteArray: this.state.noteArray})
this.saveUserTasks(this.state.noteArray)
}
goToNoteDetail=(key)=>{
this.props.navigation.navigate('DetailsScreen', {
selectedTask: this.state.noteArray[key],
});
}
}
in detail view I have this method which is similar to add note in main class:
export default class Details extends React.Component {
render() {
const { navigation } = this.props;
const selectedTask = navigation.getParam('selectedTask', 'task');
return(
<View key={this.props.keyval} style={styles.container}>
<TouchableOpacity onPress={this.saveEdit.bind(this)} style={styles.saveButton}>
<Text style={styles.saveButtonText}> save </Text>
</TouchableOpacity>
</View>
);
}
saveEdit(){
let selectedItem = { 'creationDate': selectedTask['creationDate'],
'taskName': selectedTask['taskName'],
'dueDate': this.state.dueData}
this.props.navigation.state.params.saveEdit(selectedItem)
}
}
How can I change my props in any component?
First of all you shouldn't call this.getUserTasks() in the render method because the function has this.setState which is bad and could end in a endless loop I guess or at least effect in worse performance. You could instead call it in componentDidMount:
componentDidMount = () => {
this.getUserTasks();
}
Or alternatively call already in constructor but I prefer the first option:
constructor(props){
super(props);
this.state = {
noteArray: [],
noteText: '',
dueDate: ''
};
this.getUserTasks()
}
this.props.noteArray.push({.. is probably undefined because you aren't passing it down any where. (Didn't see any reference in your snippet). I guess I would implement the saveEdit function in the Main.js component and simply pass it down to the navigation route and call the function in Details component by accessing the navigation state props:
Update
goToNoteDetail=(key)=>{
this.props.navigation.navigate('DetailsScreen', {
// selectedTask: this.state.noteArray[key],
selectedItem: key,
saveEdit: this.saveEdit
});
}
saveEdit(selectedItem){
const selectedTask = this.state.noteArray[selectedItem]
this.state.noteArray.push({
'creationDate': selectedTask['creationDate'],
'taskName': selectedTask['taskName'],
'dueDate': this.state.dueData
});
this.setState({noteArray:this.state.noteArray})
this.setState({dueData: 'YYYY/MM/DD'});
this.saveUserTasks(this.state.noteArray)
}
And then call saveEdit in Details Component:
saveSelectedItem = () => {
const { navigation } = this.props.navigation;
const {selectedItem, saveEdit} = navigation.state && navigation.state.params;
saveEdit(selectedItem)
}

React-native: How to get navigationOptions with Custom TabBarComponent

I'm new to react native and i'm trying to build a custom tab bar but i'm facing a problem when trying to display icons tab bar.
Here what i achieve so far.
Here my Custom TabBar component:
class TabBar extends Component {
renderItem = (route, index) => {
const {
navigation,
jumpToIndex,
} = this.props;
const isCapture = route.routeName === 'AddExpenses';
const focused = index === navigation.state.index;
const color = focused ? activeTintColor : inactiveTintColor;
if (isCapture === true) {
return (
<TouchableOpacity
key={route.key}
style={Styles.tab}
onPress={() => (navigation.navigate('AddExpensesModal'))}
>
<Ionicons
name={ioniconsByPlatform('add-circle')}
style={Styles.icon}
size={26}
/>
</TouchableOpacity>
);
}
return (
<TouchableWithoutFeedback
key={route.key}
style={Styles.tab}
onPress={() => (isCapture ? navigation.navigate('CaptureModal') : jumpToIndex(index))}
>
<View style={Styles.tab}>
<Text style={{ color }}>{route.routeName}</Text>
</View>
</TouchableWithoutFeedback>
);
}
render() {
const {
navigation,
} = this.props;
const {
routes,
} = navigation.state;
return (
<View style={Styles.tabBar}>
{routes && routes.map(this.renderItem)}
</View>
);
}
}
export default TabBar;
My Tab Navigator:
const MainTabNavigator = TabNavigator({
Summary: { screen: SummaryScreen },
AddExpenses: { screen: ExpensesScreen },
Expenses: { screen: ExpensesScreen },
}, {
tabBarComponent: TabBar,
});
export default MainTabNavigator;
And an example of a screen where i try to set my TabBarIcon:
const SummaryScreen = () => (
<View style={Styles.container}>
<Text>Summary</Text>
</View>
);
SummaryScreen.navigationOptions = {
title: 'Summary',
tabBarIcon: props => <TabBarIcon {...props} name="pulse" />,
};
export default SummaryScreen;
I want to be able to display my tab bar icons thanks to the navigationOptions property.
Do you have any idea how i can do this ?
If you feel TabNavigator is not powerful enough(which I think it's far from powerful), you could always customize a navigator view.
Here is my notes for customize a navigator view to replace TabNavigator:
export default class SectionTabView extends React.Component {
static propTypes = {
navigation: PropTypes.object
};
constructor(props) {
super(props);
}
render() {
const {router, navigation} = this.props;
const {routes, index} = navigation.state;
/**
* ActiveScreen is the current screen you see when you change you navigation state in tab bar
*/
const ActiveScreen = router.getComponentForState(navigation.state);
return (
<View style={Styles.section_container}>
<ActiveScreen
navigation={addNavigationHelpers({
...navigation,
state: routes[index],
})}
/>
<SectionTabBar navigation={navigation}/>
</View>
);
}
}
export default class SectionTabBar extends React.Component {
static propTypes = {
navigation: PropTypes.object
};
constructor(props) {
super(props);
}
getTabButtomGroupView() {
const {navigation} = this.props;
const {routes, index} = navigation.state;
let tabButtomGroupView = [];
routes.map((route) => {
let styles = [Styles.eventSection_tab];
const isClicked = routes[index].routeName === route.routeName;
if(isClicked){
styles.push(Styles.eventSection_tabClicked);
}
tabButtomGroupView.push(
<TouchableOpacity
onPress={() => {
/**
* when the routeName is equal to current routeName, we should stop navigate action
*/
if (routes[index].routeName === route.routeName) {
return;
}
navigation.navigate(route.routeName);
}}
style={styles}
key={route.routeName}>
<Text style={{color:'white'}}>{SectionRouteConfig[route.routeName].navigationOptions.title}</Text>
</TouchableOpacity>
)
});
return tabButtomGroupView;
}
render() {
return (
<View style={Styles.section_tabContainer}>
{this.getTabButtomGroupView()}
</View>
);
};
}
//SectionRouteConfig.js
export const sectionRouteConfig = {
XXX: {
screen: XXX, navigationOptions: {
title: XXX
}
},
XXX: {
screen: XXX, navigationOptions: {
title: XXX
}
}
};
export const SectionNavigator = createNavigator(TabRouter(sectionRouteConfig))(SectionTabView);
//Usage
render() {
const {dispatch, navigationState} = this.props;
return (
<SectionNavigator
navigation={
addNavigationHelpers({
dispatch: dispatch,
state: navigationState
})
}
/>
)
}
by the way I also use redux.
If those codes are too much for you , you can check the official example here:https://github.com/react-community/react-navigation/blob/master/examples/NavigationPlayground/js/CustomTabs.js