I have looked every related topic on StackOverflow without success.
I am trying to go from a tab to another using "navigation.navigate" while passing a param. The navigation works but the param does not get passed.
here is what my TabNavigator looks like:
const handleTabPress = ({ navigation }) => {
navigation.navigate(navigation.state.routeName);
navigation.popToTop();
};
export default createBottomTabNavigator(
{
Overview: {
screen: OverviewStack,
navigationOptions: {
title: "Home",
tabBarOnPress: handleTabPress,
gesturesEnabled: false,
},
},
Profile: {
screen: ProfileStack,
resetOnBlur: true,
navigationOptions: {
title: "Profile",
tabBarOnPress: handleTabPress,
gesturesEnabled: false,
},
},
....
And my profileStack looks like this
const MainProfileStack = createStackNavigator(
{
...ProfileRoutes,
},
{
initialRouteName: "Profile",
resetOnBlur: true,
defaultNavigationOptions: ({ navigation }) => ({
...SharedHeader(navigation),
}),
}
);
const ProfileStack = createStackNavigator(
{
ProfileMain: MainProfileStack,
},
{
mode: "modal",
headerMode: "none",
}
);
You can always use redux to share data.
Related
I have a functional component and I want the navigation title to be updated to a data that I get from a data storage. There are plenty of issues and blogs but I can't even get it to update to a literarl text.
DataScreen.js
import React, {useEffect} from 'react';
import {
Button
} from 'react-native';
const DataScreen: () => React$Node = (props) => {
const { navigation } = props;
// didnt work
const updateTitle = () =>{
console.log('trying to update title')
navigation.setParams({
Title: 'New Title', // tired title as well
});
}
useEffect(() => {
updateTitle();
}, []);
return (
<>
<Button title="New Title" onPress={updateTitle} />
</>
);
};
DataScreen.navigationOptions = {
title: ' New Title',
}
export default DataScreen;
if i do console.log(navigation) after calling updateTitle, I see "New Title". Hence, I think it is being set but not reflected in the UI.
my navigator object:
createStackNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: ({navigation}) => ({
title: 'Home',
}),
},
Data: {
screen: DataScreen,
navigationOptions: ({navigation}) => ({
title: 'Data'
}),
},
},
{
initialRouteName: 'Home',
headerMode: 'screen',
mode: 'card'
},
);
There are 2 ways to do this
Update your createStackNavigator to reference the title from route.params.title (or Title, if you used capital T)
createStackNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: ({navigation}) => ({
title: navigation.state.params.title, // or Title if you use capital T
}),
},
Data: {
screen: DataScreen,
navigationOptions: ({navigation}) => ({
title: navigation.state.params.title
}),
},
},
{
initialRouteName: 'Home',
headerMode: 'screen',
mode: 'card'
},
);
or
Change setParams to setOptions (without changing anything in createStackNavigator)
const DataScreen: () => React$Node = (props) => {
const { navigation } = props;
// didnt work
const updateTitle = () =>{
console.log('trying to update title')
// navigation.setParams({
// Title: 'New Title', // tired title as well
// });
navigation.setOptions({
Title: 'New Title', // tired title as well
});
}
useEffect(() => {
updateTitle();
}, []);
return (
<>
<Button title="New Title" onPress={updateTitle} />
</>
);
};
I am making react native expo app and i need your help.
I have structure:
main.js => page1.js => page2.js
When i move from main.js to page1.js in createStackNavigator i write title of header of page1.js, but in page1.js i hide the header of page1.js and i have all ok, but when i move to page2.js i have 3 headers!!!!
One of them i hide in page2.js but one other header i do not how to hide, because 1 header is coming from main.js but second from page1.js and i need to hide this header from main.js but if i hide it i will not have header in page1.js.
I want when i navigate to page2.js from page1.js i send data to main.js createStackNavigator. How i can do this??
Code:
// main.js createStackNavigator:
export default createStackNavigator(
{
Main: {
screen: Main,
navigationOptions: {
header: null,
},
},
Page1: {
screen: Page1,
navigationOptions: ({ navigation }) => ({
headerTitle: "Page1",
}),
},
},
{
initialRouteName: 'Main',
}
);
// Page1.js createStackNavigator:
export default createStackNavigator(
{
Main: {
screen: Page1,
navigationOptions: {
header: null,
},
},
Page2: {
screen: Page2,
navigationOptions: ({ navigation }) => ({
headerTitle: "Text",
}),
},
},
{
initialRouteName: 'Main',
}
);
// Page2:
export default createStackNavigator(
{
Main: {
screen: Page2,
navigationOptions: {
header: null,
},
},
},
{
initialRouteName: 'Main',
}
);
You are duplicating rout names, Main is used 3 times,
also page1 and page2 have 2 different routes each,
solution is to create call createStackNavigator in seperate file or in app.js like
export default createStackNavigator(
{
Main: {
screen: Main,
navigationOptions: {
header: null,
},
},
Page1: {
screen: Page1,
navigationOptions: ({ navigation }) => ({
headerTitle: "Page1",
}),
},
Page2: {
screen: Page2,
navigationOptions: ({ navigation }) => ({
headerTitle: "Text",
}),
},
},
{
initialRouteName: 'Main',
}
);
now all the screens will have same header and you can change the title in navigationOptions
We are showing navigation side drawer in our react native application.
So, In that, For particular screen, We have to disable gestures.
And for complete app, We are hiding navigation header too.
MyStack.navigationOptions = ({ navigation }) => {
let drawerLockMode = 'unlocked';
if ((navigation.state.index === 2) || (navigation.state.index === 3)) {
drawerLockMode = 'locked-closed';
}
return {
drawerLockMode,
header: null,
headerVisible: false,
};
};
const MyStack = createStackNavigator({
screen1: { screen: screen1, navigationOptions: { header: null, headerMode: 'none' } },
screen2: { screen: screen2, navigationOptions: { header: null, headerMode: 'none'} },
screen3: { screen: screen3, navigationOptions: { header: null, headerMode: 'none'} },
.
.
});
const MyAppStack = createAppContainer(createDrawerNavigator({
MyStack: {
screen: MyStack,
},
login: {
screen: login,
},
.
.
.
));
But, Header is still showing for all the screens.
Even we have tried for individual screen navigation header hiding, But, still not hiding.
class login extends Component<Props> {
static navigationOptions = {
header: null
};
Any suggestions?
To hide navigation header, add headerMode outside of navigationOptions. Both should be at same level.
export default createStackNavigator({
...
}, {
headerMode: 'none',
navigationOptions: {
...
}
});
Update 1
const MyAppStack = createAppContainer(createDrawerNavigator({
MyStack: {
screen: MyStack,
navigationOptions: {
header:false, // or drawerLabel: () => null
}
},
login: {
screen: login,
},
.
.
.
));
Hello Anil please try following code
MyStack.navigationOptions = ({ navigation }) => {
let drawerLockMode = 'unlocked';
if ((navigation.state.index === 2) || (navigation.state.index === 3)) {
drawerLockMode = 'locked-closed';
}
return {
drawerLockMode,
header: null,
headerVisible: false,
};
};
const MyStack = createStackNavigator({
screen1: { screen: screen1 },
screen2: { screen: screen2 },
.
}, {
headerMode: 'none',
navigationOptions: {
headerVisible: false,
});
Finally, After somany forums read and some practice, Found the best solution to restrict gestures/swipe for particular screens in React-Native Navigation. Hope this will helps someone in future.
Install following library
import getCurrentRouteName from 'react-navigation-current-route';
const MyStack = createStackNavigator({
screen1: { screen: screen1, navigationOptions: { header: null, headerMode: 'none' } },
screen2: { screen: screen2, navigationOptions: { header: null, headerMode: 'none'} },
screen3: { screen: screen3, navigationOptions: { header: null, headerMode: 'none'} },
.
.
});
MyStack.navigationOptions = ({ navigation }) => {
const currentRoute = getCurrentRouteName(navigation.state);
let drawerLockMode = 'unlocked';
if ((currentRoute === 'screen1') || (currentRoute === 'screen2')) {
drawerLockMode = 'locked-closed';
}
return {
drawerLockMode
};
};
const MyAppStack = createAppContainer(createDrawerNavigator({
MyStack: {
screen: MyStack,
},
login: {
screen: login,
},
.
.
.
));
I have a StackNavigation like this:
const AppNavigator = createStackNavigator({
Login: {
screen: Login,
navigationOptions: () => ({
title: 'Login',
headerTintColor: 'white',
headerStyle:{
backgroundColor: '#000',
elevation: 0,
showdowOpacity: 0
},
})
},
Home: {
screen: AppDrawerNavigator,
navigationOptions: () => ({
header: null
})
},
});
With a DrawerNavigator nested inside:
const AppDrawerNavigator = createDrawerNavigator({
Home: {
screen: Home,
navigationOptions: {
drawerLabel: 'Home',
gesturesEnabled: false,
}
},
Favorites: {
screen: Favorites,
navigationOptions: {
drawerLabel: 'Favorites',
}
}
},
{
drawerPosition: 'left',
contentComponent: props => <Drawer {...props} />
});
The initial route of the stack navigator is working fine
Login -> Home
But when I try navigating from Home to Favorites it navigates immediately back to Home after rendering the Favorites screen.
I am using react-navigation#2.11.2 and react-native#0.56.0
With Home being used in both stack and drawer navigator.
There are high chances of name conflicts occurring here.
Try this structure.
const Stack = {
FirstView: {
screen: FirstView
},
SecondView: {
screen: SecondView
},
ThirdView: {
screen: ThirdView
}
};
const DrawerRoutes = {
FirstViewStack: {
name: 'FirstViewStack',
screen: StackNavigator(Stack, { initialRouteName: 'FirstView' })
},
SecondViewStack: {
name: 'SecondViewStack',
screen: StackNavigator(Stack, { initialRouteName: 'SecondView' })
},
ThirdViewStack: {
name: 'ThirdViewStack',
screen: StackNavigator(Stack, { initialRouteName: 'ThirdView' })
},
};
const RootNavigator =
StackNavigator({
Drawer: {
name: 'Drawer',
screen: DrawerNavigator(
DrawerRoutes,
),
},
...Stack
},
{
headerMode: 'none'
}
);
I faced a similar issue when i tried to use a hamburger menu in my Home page (which uses stack navigator to goto other pages).
Check this Git Article also.
Consider the render of the Main component:
render() {
const { isAuthenticated } = this.props;
return (
<View>
{isAuthenticated ? <Dashboard /> : <Login />}
</View>
);
I want to lock the drawer in the Login component. Now i know that i could achieve this if Login wasn't a child of Main this way (in my Router component):
Login: {
screen: Login,
navigationOptions: () => ({
drawerLockMode: 'locked-closed',
}),
},
But since Login is a child of Main and Main has the drawer, Login will automatically have the drawer too. I've tried "overriding" it by calling this in Login:
static navigationOptions = {
drawerLockMode: 'locked-closed',
};
But no success. Here's my Router:
const Stack = {
Main: { screen: Main },
Login: {
screen: Login,
navigationOptions: () => ({
drawerLockMode: 'locked-closed',
}),
},
Outbox: { screen: Outbox },
Dashboard: { screen: Dashboard },
JobList: { screen: JobList },
CreateJob: { screen: CreateJob },
Reporting: { screen: Reporting },
JobDescription: { screen: JobDescription },
};
const DrawerRoutes = {
DrawerStack: {
name: 'DrawerStack',
screen: StackNavigator(
Stack,
{
initialRouteName: C.MAIN,
headerMode: 'none',
navigationOptions: {
gesturesEnabled: false,
},
}),
},
};
export const DrawerNavigation = StackNavigator({
Drawer: {
name: 'Drawer',
screen: DrawerNavigator(DrawerRoutes, {
contentComponent: DrawerPanel,
}),
},
...Stack,
}, { headerMode: 'none' });
Is there a way to achieve this ?