How i can get the route param in react native - react-native

How i can get the route param in react native.
onPress={() => props.navigation.navigate('SingleTour', { item } )}

This is the way you can send the item eg index.js
<TouchableOpacity onPress={() => props.navigation.navigate('SingleTour', { item } )}>
<Text>SingleTour</Text>
</TouchableOpacity>
in SingleTour.js you can get this item like this
const { item } = this.props.route.params;

I assume that you need to pass param with navigation and set param to the new screen's state.
Assuming that this is your onPress event on base screen
onPress={() => props.navigation.navigate('SingleTour', { item } )}
So this is how you set param in new screen's state
SingleTour.js
import React, { Component } from 'react';
import {
View,
StyleSheet
} from 'react-native';
export default class SingleTour extends Component {
constructor(props) {
super(props);
this.state = {
item : this.props.navigation.state.params.item,
}
}
render() {
return (
<View style={styles.container}>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
}
});
Hope you have clear about this :)

This is your solution.
onPress={() => {
/* 1. Navigate to the Details route with params */
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
If any problem occurs, you can refer to this Official Documentation
Refer this Expo Snack Online Demo

Related

How to separate axios call from component in react native?

I am new to react native. I have following component in my project for now I have written for fetching API in same component but want to separate it out. I am getting difficulty for how can i access variable which I am using in "getAlbum" method from outside of component.
Is there standard way to separate API call from component?
import React, { Component } from 'react';
import {
FlatList, Text, View, Image, TouchableOpacity,
} from 'react-native';
import { ActivityIndicator, Provider } from 'react-native-paper';
import axios from 'axios';
import styles from '../style/ThumbnailView.component.style';
import ErrorAlert from '../common/ErrorAlert';
import * as myConstant from '../common/Constants';
export default class HomeScreen extends Component {
// For to Navigation header
static navigationOptions = () => ({
headerTitle: 'Album Information',
});
constructor(props) {
super(props);
this.state = {
isLoading: true,
apiLoadingError: false,
};
}
getAlbums() {
const { navigation } = this.props;
const albumId = navigation.getParam('albumID', 'no data');
axios
.get(
myConstant.API + `photos?albumId=${albumId}`, {timeout: myConstant.TIMEOUT}
)
.then((response) => {
this.setState({
isLoading: false,
dataSource: response.data,
});
})
.catch(err => {
this.setState({isLoading: false, apiLoadingError: true})
});
}
componentDidMount() {
this.getAlbums();
}
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, paddingTop: 30 }}>
<ActivityIndicator animating={true} size='large' />
</View>
);
}
if (this.state.apiLoadingError) {
return (
<ErrorAlert />
);
}
return (
<React.Fragment>
<Provider>
<View style={styles.listContainer} >
<FlatList
testID='flatlist'
data={ this.state.dataSource } numColumns={3}
renderItem={({ item }) => <View style={styles.listRowContainer}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('AlbumDetailsViewScreen', {
albumTitle: item.title, albumImg: item.url
})} style={styles.listRow}>
<View style={styles.listTextNavVIew}>
<Image source = {{ uri: item.thumbnailUrl }} style={styles.imageViewContainer} />
</View>
</TouchableOpacity>
</View>
}
keyExtractor = { (item, index) => index.toString() }
/>
</View>
</Provider>
</React.Fragment>
);
}
}
You can separate your axios call by making another class with function which will receive 'albumID' as an argument - then add it to your axios link. If you want to call this function from another class just make it static and use like in example below. Then you can map your fetchData to parse it into state. Hope it will help you.
export class Api {
static fetchData = (albumId: string) => {
//here your axios call which will return an array
}
}
export default class HomeScreen extends React.Component {
state = {
//.....
}
receivedData = Api.fetchData('albumID');
//you can map array here to get what you want.
}

Pass Data between Pages in React native

Im new to react native and I'm stuck at following.
Im performing navigation (when clicked on alert view button) using the code below.
const {navigation} = this.props.navigation;
…
.
.
{ text: 'Done', onPress:() => {
navigate.push(HomeScreen);}
How can I pass data to another Page in React native? Can I declare the parameter global and just assign to it?
What would be the correct way of performing this and how would I go about it?
Note
This answer was written for react-navigation: "3.3.0". As there are newer versions available, which could bring changes, you should make sure that you check with the actual documentation.
Passing data between pages in react-navigation is fairly straight forward. It is clearly explained in the documentation here
For completeness let's create a small app that allows us to navigate from one screen to another passing values between the screens. We will just be passing strings in this example but it would be possible to pass numbers, objects and arrays.
App.js
import React, {Component} from 'react';
import AppContainer from './MainNavigation';
export default class App extends React.Component {
render() {
return (
<AppContainer />
)
}
}
MainNavigation.js
import Screen1 from './Screen1';
import Screen2 from './Screen2';
import { createStackNavigator, createAppContainer } from 'react-navigation';
const screens = {
Screen1: {
screen: Screen1
},
Screen2: {
screen: Screen2
}
}
const config = {
headerMode: 'none',
initialRouteName: 'Screen1'
}
const MainNavigator = createStackNavigator(screens,config);
export default createAppContainer(MainNavigator);
Screen1.js and Screen2.js
import React, {Component} from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';
export default class Screen extends React.Component {
render() {
return (
<View style={styles.container}>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
}
});
Here we have 4 files. The App.js which we will import the MainNavigation.js. The MainNavigation.js sets up a StackNavigator with two screens, Screen1.js and Screen2.js. Screen1 has been set as the initial screen for our StackNavigator.
Navigating between screens
We can navigate from Screen1 to Screen2 by using
this.props.navigation.navigate('Screen2');
and we can go back to Screen1 from Screen2 by using
this.props.navigation.goBack();
So code in Screen1 becomes
export default class Screen extends React.Component {
render() {
return (
<View style={styles.container}>
<Button title={'Go to screen 2'} onPress={() => this.props.navigation.navigate('Screen2')} />
</View>
)
}
}
And code in Screen2 becomes:
export default class Screen extends React.Component {
render() {
return (
<View style={styles.container}>
<Button title={'Go back'} onPress={() => this.props.navigation.goBack()} />
</View>
)
}
}
Now we can navigate between Screen1 and Screen2
Sending values from Screen1 to Screen2
To send a value between Screen1 and Screen2, two steps are involved. First we have to send it, secondly we have to capture it.
We can send a value by passing it as a second parameter. Notice how the text value is contained in an object.
this.props.navigation.navigate('Screen2', {text: 'Hello from Screen 1' });
And we can capture it in Screen2 by doing the following, the first value in getParams is the key the second value is the default value.
const text = this.props.navigation.getParams('text','nothing sent');
So Screen1 now becomes
export default class Screen extends React.Component {
render() {
return (
<View style={styles.container}>
<Button
title={'Go to screen 2'}
onPress={() => this.props.navigation.navigate('Screen2', {
text: 'Hello from screen 1'
})} />
</View>
)
}
}
And code in Screen2 becomes:
export default class Screen extends React.Component {
render() {
const text = this.props.navigation.getParam('text', 'nothing sent')
return (
<View style={styles.container}>
<Text>{text}</Text>
<Button
title={'Go back'}
onPress={() => this.props.navigation.goBack()} />
</View>
)
}
}
Sending values from Screen2 back to Screen1
The easiest way I have discovered to send a value from Screen2 to Screen1 is to pass a function to Screen2 from Screen1 that will update the state in Screen1 with the value that you want to send
So we can update Screen1 to look like this. First we set an initial value in state. Then we create a function that will update the state. Then we pass that function as a parameter. We will display the captured value from Screen2 in a Text component.
export default class Screen1 extends React.Component {
state = {
value: ''
}
receivedValue = (value) => {
this.setState({value})
}
render() {
return (
<View style={styles.container}>
<Button
title={'Go to screen 2'}
onPress={() => this.props.navigation.navigate('Screen2', {
text: 'Hello from Screen 1',
receivedValue: this.receivedValue }
)} />
<Text>{this.state.value}</Text>
</View>
)
}
}
Notice that we are passing the function receivedValue in the same way that we passed the text earlier.
Now we have to capture the value in Screen2 and we do that in a very similar way that we did previously. We use getParam to get the value, remembering to set our default. Then when we press our Go back button we update it to call the receivedValue function first, passing in the text that we want to send back.
export default class Screen2 extends React.Component {
render () {
const text = this.props.navigation.getParam('text', 'nothing sent');
const receivedValue = this.props.navigation.getParam('receivedValue', () => {});
return (
<View style={styles.container}>
<Button
title={'Go back'}
onPress={() => {
receivedValue('Hello from screen 2')
this.props.navigation.goBack()
}} />
<Text>{text}</Text>
</View>
);
}
}
Alternatives to using getParam
It is possible to not use the getParam method and instead access the values directly. If we were to do that we would not have the option of setting a default value. However it can be done.
In Screen2 we could have done the following:
const text = this.props.navigation.state.params.text;
const receivedValue = this.props.navigation.state.params.receivedValue;
Capturing values in lifecycle events (Screen1 to Screen2)
react-navigation allows you to capture values using the lifecycle events. There are a couple of ways that we can do this. We could use NavigationEvents or we could use listeners set in the componentDidMount
Here is how to set it up using NavigationEvents
import React, {Component} from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { NavigationEvents } from 'react-navigation'; // you must import this
export default class Screen2 extends React.Component {
state = {
text: 'nothing passed'
}
willFocusAction = (payload) => {
let params = payload.state.params;
if (params && params.value) {
this.setState({value: params.value});
}
}
render() {
return (
<View style={styles.container}>
<NavigationEvents
onWillFocus={this.willFocusAction}
/>
<Text>Screen 2</Text>
<Text>{this.state.text}</Text>
</View>
)
}
}
Here is how to do it using listeners in the componentDidMount
export default class Screen2 extends React.Component {
componentDidMount () {
// we add the listener here
this.willFocusSubscription = this.props.navigation.addListener('willFocus', this.willFocusAction);
}
componentWillUmount () {
// we remove the listener here
this.willFocusSubscription.remove()
}
state = {
text: 'nothing passed'
}
willFocusAction = (payload) => {
let params = payload.state.params;
if (params && params.value) {
this.setState({value: params.value});
}
}
render() {
return (
<View style={styles.container}>
<Text>Screen 2</Text>
<Text>{this.state.text}</Text>
</View>
)
}
}
Passing navigation via components
In the above examples we have passed values from screen to screen. Sometimes we have a component on the screen and we may want to navigate from that. As long as the component is used within a screen that is part of a navigator then we can do it.
If we start from our initial template and construct two buttons. One will be a functional component the other a React component.
MyButton.js
// this is a functional component
import React, {Component} from 'react';
import { View, StyleSheet, Text, TouchableOpacity } from 'react-native';
export const MyButton = ({navigation, value, title}) => {
return (
<TouchableOpacity onPress={() => navigation.navigate('Screen2', { value })}>
<View style={styles.buttonStyle}>
<Text>{title}</Text>
</View>
</TouchableOpacity>
)
}
const styles = StyleSheet.create({
buttonStyle: {
width: 200,
height: 60,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'red'
}
});
MyOtherButton.js
// this is a React component
import React, {Component} from 'react';
import { View, StyleSheet, Text, TouchableOpacity } from 'react-native';
export default class MyOtherButton extends React.Component {
render() {
const { navigation, value, title } = this.props;
return (
<TouchableOpacity onPress={() => navigation.navigate('Screen2', { value })}>
<View style={styles.buttonStyle}>
<Text>{title}</Text>
</View>
</TouchableOpacity>
)
}
}
const styles = StyleSheet.create({
buttonStyle: {
width: 200,
height: 60,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'yellow'
}
});
Regardless of the type of component, notice that navigation is a prop. We must pass navigation to the component otherwise it will not work.
Screen1.js
import React, {Component} from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';
import { MyButton } from './MyButton';
import MyOtherButton from './MyOtherButton';
export default class Screen1 extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Screen 1</Text>
<MyButton
title={'Press my button'}
navigation={this.props.navigation}
value={'this is a string passed using MyButton'}
/>
<MyOtherButton
title={'Press my other button'}
navigation={this.props.navigation}
value={'this is a string passed using MyOtherButton'}
/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
}
});
Notice in Screen1.js as it is contained in a StackNavigator it will have access to this.props.navigation. We can pass that through to our component as a prop. As long as we use that in our component then we should be able to navigate by using the components own functionality.
<MyButton
title={'Press my button'}
navigation={this.props.navigation} // pass the navigation here
value={'this is a string passed using MyButton'}
/>
Snacks
Here is a snack for passing params.
Here is a snack for passing params and capturing in lifecycle events.
Here is a snack passing navigation to components
1) On Home Screen:-
Initialise:-
constructor(props) {
super(props);
this.navigate = this.props.navigation.navigate; }
Send:-
this.navigate("DetailScreen", {
name: "Detail Screen",
about:"This is Details Screen Page"
});
2) On Detail Screen:-
Initialise:-
constructor(props) {
super(props);
this.params = this.props.navigation.state.params;
}
Retrive data:-
console.log(this.params.name);
console.log(this.params.about);
const {navigate} = this.props.navigation;
…
.
.
{ text: 'Done', onPress:() => {
navigate('homeScreen',...params);}
You can get those params like
const {params} = this.props.navigation.state
HomeScreen.js
this.props.navigation.navigate('Screen2',{ user_name: 'aaa',room_id:'100' });
Screen2.js
const params = this.props.route.params;
user_name = params.user_name;
room_id = params.room_id
You can easily send and receive your params with react-navigation like below
Send params:
{
text: 'Done',
onPress: () => {
this.props.navigation.navigate(
HomeScreen,
{param1: 'value1', param2: 'value2'}
);
}
}
Get params in HomeScreen:
const { navigation } = this.props;
var param1 = navigation.getParam('param1', 'NO-VALUE');
var param2 = navigation.getParam('param2', 'NO-VALUE');
the 'NO-VALUE' is default value, if there is not desired param
I am assuming that you are using react-navigation. So, in react-navigation we can pass data in two pieces:
Pass params to a route by putting them in an object as a second parameter to the navigation.navigate function:
this.props.navigation.navigate('RouteName', { /* params go here */ })
Read the params in your screen component:
this.props.navigation.getParam(paramName, someDefaultValue)
Alert Button
<Button
title="Alert View"
onPress={() => {
this.props.navigation.navigate('alerts', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
/>
Screen:
const itemId = navigation.getParam('itemId', 'NO-ID');
const otherParam = navigation.getParam('otherParam', 'some default value')
Screen 1:
<Button title="Go Next"
onPress={() => navigation.navigate('SecondPage', { paramKey: userName })} />
Screen 2:
const SecondPage = ({route}) => {
....
....
<Text style={styles.textStyle}>
Values passed from First page: {route.params.paramKey}
</Text>
....
....
}

react-native componentWillUnmount not working while navigating

I am doing this simple steps but unmount was not calling I don't know why. Please I need a solution for this I need unmount to be get called while navigating to another screen...
class Homemain extends Component {
constructor(props) {
super(props);
}
componentWillMount(){
alert('willMount')
}
componentDidMount(){
alert('didMount')
}
componentWillUnmount(){
alert('unMount')
}
Details = () => {
this.props.navigation.navigate('routedetailsheader')
}
render() {
return(
<View style={styles.container}>
<TouchableOpacity onPress={() => this.Details()} style={{ flex: .45, justifyContent: 'center', alignItems: 'center', marginTop: '10%', marginRight: '10%' }}>
<Image
source={require('./../Asset/Images/child-notification.png')}
style={{ flex: 1, height: height / 100 * 20, width: width / 100 * 20, resizeMode: 'contain' }} />
<Text
style={{ flex: 0.5, justifyContent: 'center', fontSize: width / 100 * 4, fontStyle: 'italic', fontWeight: '400', color: '#000', paddingTop: 10 }}>Details</Text>
</TouchableOpacity>
</View>
);
}
}
export default (Homemain);
This is my RouteConfiguration in this way I am navigating to the next screen. Can someone please help me for this error so that i can proceed to the next steps
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { addNavigationHelpers, NavigationActions } from 'react-navigation';
import { connect } from 'react-redux';
import { BackHandler } from 'react-native';
import { Stack } from './navigationConfiguration';
const getCurrentScreen = (navigationState) => {
if (!navigationState) {
return null
}
const route = navigationState.routes[navigationState.index]
if (route.routes) {
return getCurrentScreen(route)
}
return route.routeName
}
class StackNavigation extends Component {
static propTypes = {
dispatch: PropTypes.func.isRequired,
navigation: PropTypes.shape().isRequired,
};
constructor(props) {
super(props);
BackHandler.addEventListener('hardwareBackPress', this.backAction);
}
//backAction = () => this.navigator.props.navigation.goBack();
backAction = () => {
const { dispatch, navigation } = this.props;
const currentScreen = getCurrentScreen(navigation)
if (currentScreen === 'Homemain') {
return false
}
else
if (currentScreen === 'Login') {
return false
}
dispatch(NavigationActions.back());
return true;
};
render() {
const { dispatch, navigation } = this.props;
return (
<Stack
ref={(ref) => { this.navigator = ref; }}
navigation={
addNavigationHelpers({
dispatch,
state: navigation,
})
}
/>
);
}
}
export default connect(state => ({ navigation: state.stack }))(StackNavigation);
Routing to a new screen does not unmount the current screen.
For you usecase you instead of writing the code in componentWillUnmount you can continue by writing it after calling navigate in Details itself.
If you are looking for a callback when you press back from the new screen to come back to the current screen. Use goBack as shown in https://github.com/react-navigation/react-navigation/issues/733
If you are using a stack navigator, then routing to a new view loads the new view above the old one. The old view is still there for when you navigate back.
As I understand from your question and code you are using redux with navigation and want to unmount a screen. So what I did I just added a screen component inside another component to make my screen component as child.
e.g. below is the snippet that I am using to unmount the PushScreen from PushedData component.
I render PushScreen and inside it there is component PushedData that originally making the view. On PushedData `componentWillMount I am just doing some conditional functionality and on success I am just unmounting PushData from PushScreen.
class PushScreen extends Component{
state ={ controllerLaunched: false };
updateControllerLauncher = () => {
this.setState({ controllerLaunched: true });
}
render (){
if(this.state.controllerLaunched){
return null;
} else {
return <PushedData handleControllerLauncher={this.updateControllerLauncher} />;
}
}
}
class PushedData extends Component{
componentWillMount(){
this.unmountPushData();//calling this method after some conditions.
}
unmountPushData = () => {
this.props.handleControllerLauncher();
}
render(){
return (
<View><Text>Component mounted</Text></View>
);
}
}
Let me know if you need more information.
When you use Stack Navigator then routing to a new view loads the new view above the old one as Rob Walker said. There is a workaround. You can bind blur event listener on componentDidMount using navigation prop:
componentDidMount() {
this.props.navigation.addListener('blur', () => {
alert('screen changed');
})
}
So when your screen goes out of focus the event listener is called.
You can find more about events right here.
If you want to go next Screen use (.replace instead .navigate) where you want to call componentWillUnmount. and if you want to go back to one of previous screens use .pop or .popToTop.
you can set condition for costume function that u write for hardware button , for example when ( for example for React Native Router Flux ) Actions.currentScene === 'Home' do something or other conditions u want .

react native Flatlist navigation

I m getting error
TypeError: Cannot read property 'navigation' of undefined. I don't understand how to pass navigation component into each child so when a user presses an item it can navigate to employeeEdit component using React Navigation. i am newbie sorry if this is obvious.
import React, { Component } from 'react';
import { FlatList } from 'react-native';
import { connect } from 'react-redux';
//import { R } from 'ramda';
import _ from 'lodash';
import { employeesFetch } from '../actions';
import { HeaderButton } from './common';
import ListEmployee from './ListEmployee';
class EmployeeList extends Component {
static navigationOptions = ({ navigation }) => ({
headerRight: (
<HeaderButton onPress={() => navigation.navigate('employeeCreate')}>
Add
</HeaderButton>
)
});
componentWillMount() {
this.props.employeesFetch();
}
keyExtractor(item) {
return item.uid;
}
renderItem({ item }) {
return <ListEmployee employee={item} navigation={this.props.navigation} />;
}
render() {
return (
<FlatList
data={this.props.employees}
renderItem={this.renderItem} // Only for test
keyExtractor={this.keyExtractor}
navigation={this.props.navigation}
/>
);
}
}
const mapStateToProps = (state) => {
const employees = _.map(state.employees, (val, uid) => ({ ...val, uid }));
return { employees };
};
export default connect(mapStateToProps, { employeesFetch })(EmployeeList);
Here's the code for ListEmployee
import React, { Component } from 'react';
import {
Text,
StyleSheet,
TouchableWithoutFeedback,
View
} from 'react-native';
import { CardSection } from './common';
class ListEmployee extends Component {
render() {
const { employee } = this.props;
const { navigate } = this.props.navigation;
const { textStyle } = styles;
const { name } = this.props.employee;
return (
<TouchableWithoutFeedback onPress={() => navigate('employeeEdit', { employee })}>
<View>
<CardSection>
<Text style={textStyle}>{name}</Text>
</CardSection>
</View>
</TouchableWithoutFeedback>
);
}
}
/**
second argument in connect does 2 things. 1. dispatches all actions creators
return action objects to the store to be used by reducers; 2. creates props
of action creators to be used by components
**/
export default ListEmployee;
const styles = StyleSheet.create({
textStyle: {
fontSize: 18,
paddingLeft: 15,
}
});
This is one ES6 common pitfall. Don't worry my friend, you only have to learn it once to avoid them all over again.
Long story short, when you declare a method inside React Component, make it arrow function
So, change from this.
renderItem({ item }) {
to this
renderItem = ({ item }) => {
That should solve your problem, for some inconvenient reason, you can only access "this" if you declare your method as an arrow function, but not with normal declaration.
In your case, since renderItem is not an arrow function, "this" is not referred to the react component, therefore "this.props" is likely to be undefined, that is why it gave you this error Cannot read property 'navigation' of undefined since
this.props.navigation = (undefined).navigation
Inside your renderItem method, you can manage what happens when the user presses one an item of your FlatList:
renderItem({ item }) {
<TouchableOpacity onPress={() => { this.props.navigator.push({id: 'employeeEdit'})}} >
<ListEmployee employee={item} navigation={this.props.navigation} />
</TouchableOpacity>
}
Hope it help you!
A navigation sample
here VendorList is the structure rendered
<FlatList
numColumns={6}
data={state.vendoreList}
keyExtractor={(data) => data.id}
renderItem={({ item }) =>
<TouchableOpacity onPress={() => props.navigation.navigate("Home1")} >
<VendorList item={item} />
</TouchableOpacity>
}
/>
in ListEmployee
const {navigation}= this.props.navigation;
this use
<TouchableWithoutFeedback onPress={() => navigation.navigate('employeeEdit', { employee })}>
just need to modification on those two lines, i make text bold what changes you need to do

Flux (alt), TabBarIOS, and Listeners and tabs that have not yet been touched / loaded

I've got a problem that I'm sure has a simple solution, but I'm new to React and React Native so I'm not sure what I'm missing.
My app has a TabBarIOS component at its root, with two tabs: TabA and TabB. TabB is subscribed to events from a Flux store (I'm using alt) that TabA creates. TabA basically enqueues items that TabB plays. This part of the code is fine and works as expected.
The problem is that TabA is the default tab so the user can use TabA an enqueue items, but because TabB hasn't been touched/clicked the TabB component hasn't been created so it's listener hasn't been registered. Only when TabB is pressed does it get created and correctly receive events.
So how can I ensure the TabB component gets created when the TabBarIOS component is rendered? Do I need to something hacky like set the active tab to TabB on initial load and flip it back to TabA before the user does anything?
Yes, you'll need to do something hacky if you're not using a Navigator component. If you're using Navigatoryou can specify a set of routes to initially mount with the initialRouteStackprop. This is however going to need you to modify a bit the way your app works I think.
If not using Navigator, you'll indeed have to do something hacky as you suggested. I've set up a working example here based on RN's TabBar example.
Below you'll find the code of this example, check the console.log (they don't seem to work on rnplay) to see that that components are mounted on opening the app.
Example Code
var React = require('react-native');
var {
AppRegistry,
Component,
Image,
StyleSheet,
TabBarIOS,
Text,
View
} = React;
import _ from 'lodash';
var base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg==';
class StackOverflowApp extends Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'blueTab',
notifCount: 0,
presses: 0
};
}
_renderContent = (color, pageText, num) => {
return (
<View style={[styles.tabContent, {backgroundColor: color}]}>
<Text style={styles.tabText}>{pageText}</Text>
<Text style={styles.tabText}>{num} re-renders of the {pageText}</Text>
</View>
);
};
componentWillMount() {
this.setState({selectedTab: 'redTab'});
}
componentDidMount() {
this.setState({selectedTab: 'blueTab'});
}
render () {
return (
<View style={{flex: 1}}>
<TabBarIOS
tintColor="white"
barTintColor="darkslateblue">
<TabBarIOS.Item
title="Blue Tab"
icon={{uri: base64Icon, scale: 3}}
selected={this.state.selectedTab === 'blueTab'}
onPress={() => {
this.setState({
selectedTab: 'blueTab',
});
}}>
<Page1 />
</TabBarIOS.Item>
<TabBarIOS.Item
systemIcon="history"
badge={this.state.notifCount > 0 ? this.state.notifCount : undefined}
selected={this.state.selectedTab === 'redTab'}
onPress={() => {
this.setState({
selectedTab: 'redTab'
});
}}>
<Page2 />
</TabBarIOS.Item>
</TabBarIOS>
</View>
);
};
}
class Page1 extends Component {
static route() {
return {
component: Page1
}
};
constructor(props) {
super(props);
}
componentWillMount() {
console.log('page 1 mount');
}
componentWillUnmount() {
console.log('page 1 unmount');
}
render() {
return (
<View style={styles.tabContent}>
<Text style={styles.tabText}>Page 1</Text>
</View>
);
}
}
class Page2 extends Component {
static route() {
return {
component: Page2
}
};
constructor(props) {
super(props);
}
componentWillMount() {
console.log('page 2 mount');
}
componentWillUnmount() {
console.log('page 2 unmount');
}
render() {
return (
<View style={styles.tabContent}>
<Text style={styles.tabText}>Page 2</Text>
</View>
);
}
}
const styles = StyleSheet.create({
tabContent: {
flex: 1,
backgroundColor: 'green',
alignItems: 'center',
},
tabText: {
color: 'white',
margin: 50,
},
});
AppRegistry.registerComponent('StackOverflowApp', () => StackOverflowApp);