How to send parameters from screen to stack navigator? - react-native

I am a newbie to react native.
I am using a stack navigator inside a tab navigator; I have to navigate multiple screens inside each tab. i am able to send parameters from my default class HomePage to my nested classes in my tab and stack navigators.
export const MyApp = TabNavigator({
Asset: {
screen: AssetScreen,
},
Sensors: {
screen: sensorsStack,
},
Settings: {
screen: settingStack
},
}
export const sensorsStack = StackNavigator({
sensors : { screen: SensorScreen },
sensorDetails : { screen: SensorDetails }
});
export const settingStack = StackNavigator({
settings: { screen: SettingsScreen },
about : { screen: About },
environment : { screen: Environment }
});
export default class HomePage extends Component {
constructor(props) {
super(props);
this.state = {
assetID:'xyz',
authToken:'xyzz'
}
}
static navigationOptions = {
header: null
};
render() {
const screenProps = {
asset: {
assetID: this.state.assetID,
authToken : this.state.authToken,
},
}
return (
<MyApp screenProps={screenProps} />
);
}
}
Now, i want to send a parameter from 'SensorScreen' to 'SensorDetails'. I have tried sending parameters using
NavigationActions.navigate({ routeName: 'sensorDetails' ,params: { sensorType:'Fuel',}});
from 'SensorScreen' class. But was not able to get the parameter in 'SensorDetails' class. How can i pass this params?

A little late answer but might help others that ends up here.
Instead of using NavigationActions you could try navigation from sensorScreen to sensorDetails with navigate and passing some extra variables.
this.props.navigation.navigate('SensorDetails',{sensorType:'Fuel'})
The passed object can then be read in the second screen by
this.props.navigation.state.params.sensorType
A minimal example of the case can be seen in these lines. Observe that this is a stupid on icon tab bar. But it is kept that way since the question was about a tab bar with stacks on each tab. And new tabs are easily added.
import React,{Component} from 'react'
import { Text, View, Footer,Button } from 'react-native'
import {StackNavigator,TabNavigator} from 'react-navigation'
export class SensorScreen extends React.Component {
render() {
return (<Button
onPress={() => this.props.navigation.navigate('SensorDetails',{sensorType:'Fuel'})}
title="Go to Sensor Details"
/>)}}
export class SensorDetails extends React.Component {
render() {
return (<View>
<Text>{this.props.navigation.state.params.sensorType}</Text>
</View>);}
}
const sensorsStack = StackNavigator({
sensors : { screen: SensorScreen },
SensorDetails : { screen: SensorDetails }
});
const MyApp = TabNavigator({
Sensors: {
screen: sensorsStack,
},
});
export default class Nested extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<MyApp/>
);
}
}
Hope this helps.

Related

How do i switch screens from one file to another

I'm very new to react native so please explain carefully.i have 3 files App.js SplashAndLogin.js and Register.js Im able to get from the initial screen to the register screen and go back and forth between my components in my Register file but when its time to go back to the Login screen i always seem to get the same error.
I've tried several different things but they all keep giving me the same error. im starting to think the way i set up my files are just wrong.
//App.js
class App extends Component<Props> {
render() {
return (
<AppContainer/>
)
}
}
export default App
const AppSwitchNavigator = createSwitchNavigator(
{
Login: {screen: SplashAndLogin},
//Registe :{screen: Register}
});
//SplashAndLogin.js
class SplashAndLogin extends Component<Props> {
render() {
return (
<AppContainer/>
)
}
}
export default SplashAndLogin;
const SAndLAppNavigator = createSwitchNavigator(
{
SandL : {screen: LoadingScreen },
RegisterScreen : {screen: Register}
}
);
//Register.js
export default class Application extends Component<Props> {
render() {
return (
<AppContainer/>
);
}
}
const AppSwitchNavigator = createStackNavigator(
{
Login :{screen: NameScreen},
PhoneAndEmail: {screen: EmailPasswordScreen},
HomeScreen: {screen: SplashAndLogin },
UploadScreen: {screen: CertificateUploadScreen }
});
const AppContainer = createAppContainer(AppSwitchNavigator);
So to summarize i can get to every screen except when im on the Register.js file and try to navigate to the HomeScreen it throws out the error
"The component for route 'HomeScreen' must be a react component For example...."
It's normal, you are using two different AppContainer.
You can not call a view in another AppContainer from the current AppContainer
this.props.navigation
refers to the current navigation
Use the state to change AppContainer
class RenderAppContainer extends Component {
constructor(props) {
super(props);
this.state = { IsConnected : false }
this.changeIsConnected = this.changeIsConnected.bind(this)
}
changeIsConnected = () => {
this.setState((prevState, props ) => ({ IsConnected : !prevState.IsConnected}))
}
render() {
cons {IsConnected } = this.state
return(
<React.Fragment>
{(IsConnected) ? AppContainerOne : AppContainerTwo } 
</React.Fragment
)
}
}
You can then pass changeIsConnected to your AppContainer
<AppContainerOne screenProps={{changeConnected: this.changeIsConnected}} />
<AppContainerTwo screenProps={{changeConnected: this.changeIsConnected}} />
https://reactnavigation.org/docs/en/stack-navigator.html
see documentation for ScreenProps

How to pass login credentials to initial screen of DrawerMenu of navigation drawer in React Native?

I have created React-navigation Drawer V3 in my app. I am facing the problem of getting the login credentials on the initial screen that is the "Home" screen of my drawer navigation stack. Although I am passing the data on DrawerMenu.js from Login.js with the help of :
this.props.navigation.navigate('DrawerMenu', {
loginData: loginData
})
and getting the data on DrawerMenu.js with :
constructor(props) {
super(props)
this.state = {
loginData: props.navigation.state.params.loginData
}
}
But I need to get this data to Home.js which I am not able to get. The reason of getting the data to DrawerMenu.js was because there are several other screens in the stack which want the logindata and they are able to get it using screenProps used in drawer content component but as Home is the initial screen so there no way that it receives the data on the first time, only the DrawerMenu.js file receives it initially. Can someone help me out on this?
Here is my code of DrawerMenu with navigation stack.
class DrawerMenu extends Component {
constructor(props) {
super(props)
this.state = {
loginData: props.navigation.state.params.loginData
}
}
static navigationOptions =
{
header: null,
};
render() {
return (
<SafeAreaView style={styles.droidSafeArea}>
<MyApp screenProps={{ loginData: this.state.loginData}} />
</SafeAreaView>
)
}
}
class Hidden extends React.Component {
render() {
return null;
}
}
const MainScreenNavigator = createStackNavigator({
Home: { screen: Home },
Screen1: {
screen: Screen1
},
Screen2: {
screen: Screen2
},
Screen3: {
screen: Screen3
}
},
{
initialRouteName: 'Home',
});
const MyDrawerNavigator = createDrawerNavigator(
{
Main: {
screen: MainScreenNavigator,
navigationOptions: {
drawerLabel: <Hidden />
}
}
},
{
drawerWidth: 300,
contentComponent: DrawerComponent
});
const MyApp = createAppContainer(MyDrawerNavigator);
export default DrawerMenu;
I am using :
"react-native" : "0.57.5",
"react": "16.6.1",
"react-navigation": "^3.5.1"
You can use AsyncStorage to save the data
To store
_storeData = async () => {
try {
await AsyncStorage.setItem('Key Value', 'Item Value');
} catch (error) {
// Error saving data
}
};
To retrieve
_retrieveData = async () => {
try {
const value = await AsyncStorage.getItem('Key Value');
if (value !== null) {
// We have data!!
console.log(value);
}
} catch (error) {
// Error retrieving data
}
};
Or you can use redux.

Remove navigation header on screen for react native app

I want to remove header from my screen where I use bottom tab navigator.
Here is code example:
export class Home extends Component {
render() {
return <ProductList />;
}
}
export class Settings extends Component {
render() {
return <Chat />;
}
}
const Main = createBottomTabNavigator({
Home: {
screen: Home,
navigationOptions: {
header: null,
},
},
Settings: {
screen: Settings,
},
});
navigationOptions for header seams to be ignored
navigationOptions: {
header: null,
},
But when I use navigation option on single page without createBottomTabNavigator it works.
Any ideas?
You can use this instead of above
export class Home extends Component {
static navigationOptions = {
header: {
visible: false,
}
}
render() {
return <ProductList />;
}
}
export class Settings extends Component {
render() {
return <Chat />;
}
}
const Main = createBottomTabNavigator({
Home: {
screen: Home
},
Settings: {
screen: Settings,
},
},
{
headerMode: 'screen'
});
Hope this will help you

React native navigation from seperated class files

I'm just started learning React Native. Used create-react-native-app. Code works as well. I can navigate my screen to Details from HomeScreen.
App.js file:
class HomeScreen extends React.Component {
render() {
_onPressButton() {
this.props.navigation.navigate('DetailsScreen');
}
return (
// Views
);
}
}
class DetailsScreen extends React.Component {
render() {
return (
// Views
);
}
}
const RootStack = StackNavigator(
{
HomeScreen: { screen: HomeScreen, },
DetailsScreen: { screen: DetailsScreen, },
},
{ initialRouteName: 'HomeScreen', }
);
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
Then i separated HomeScreen and DetailScreen into individual js file from App.js file. And now i am unable to navigate them. What makes it unable to navigate them?
App.js file:
import ...
import HomeScreen from './screens/homeScreen';
import DetailsScreen from './screens/detailsScreen';
const RootStack = StackNavigator(
{
HomeScreen: {screen: HomeScreen,},
DetailsScreen: {screen: DetailsScreen,}
},
{ initialRouteName: 'HomeScreen', }
);
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
HomeScreen.js file
import ...
export default class HomeScreen extends React.Component {
_onPressButton() {
Alert.alert('You tapped the button!');
this.props.navigation.navigate('DetailScreen');
}
render() {
return (
// View
);
}
}

Q: ReactNative StackNavigator inside DrawerNavigator

is there any good no bugs example with StackNavigator inside DrawerNavigator?
As in my example when the drawer is open the top Navigation title is hidden and I can't open the drawer(with slide) when I am inside the NewScreen page.
So I want to open the drawer over the title and from any page.
Thanks
http://image.prntscr.com/image/eb4d869acbcf4d22a08159b072aae930.png
Here is the code
import React, { Component } from 'react';
import {
AppRegistry,
Button,
Platform,
ScrollView,
StyleSheet,
TouchableHighlight,
Text,
} from 'react-native';
import {
DrawerNavigator,StackNavigator
} from 'react-navigation';
import FontAwesome from "react-native-vector-icons/FontAwesome";
class ScreenHome extends Component{
static navigationOptions = {
title: 'ScreenHome',
};
render() {
const { navigate } = this.props.navigation;
return (
<Button
title="Go to Jane's profile"
onPress={() => navigate('New', { name: 'Jane' })}
/>
);
}
}
class NewScreen extends Component{
static navigationOptions = {
title: 'New screen',
};
render() {
const { navigate } = this.props.navigation;
return (
<Text>Some new screen</Text>
);
}
}
class ScreenRegister extends Component{
static navigationOptions = {
title: 'ScreenRegister',
};
render(){
return <Text>ScreenRegister</Text>
}
}
const MainScreenNavigator = DrawerNavigator({
Recent: {
screen: ScreenHome
},
All: {
screen: ScreenRegister
},
});
export default SimpleApp = StackNavigator({
Home: {
screen: MainScreenNavigator
},
Chat: {
screen: ScreenHome
},
New: {
screen: NewScreen
}
});
AppRegistry.registerComponent('naviTest', () => SimpleApp);
If I got your questions correctly, you want:
1) To have access to the drawer from any page
2) Your drawer to cover the title bar when open.
To achieve Number 1
There are two ways you can do it and they are:
a) Add a button/Icon that triggers the drawer on click. When you use this solution, you will still not have the slide from left functionality as this is controlled explicitly by the DrawerNavigator
b) Add NewScreen to your Drawer since you want to have access to the entire drawer when you are within the screen
To achieve Number 2
This is a very common issue when nesting DrawerNavigator within StackNavigator. To resolve this, modify StackNavigator thus
export default SimpleApp = StackNavigator({
Home: {
screen: MainScreenNavigator
},
Chat: {
screen: ScreenHome
},
New: {
screen: NewScreen
}
}, {
navigationOptions: { header: false }
});