setParams not reflecting change in title of the UI - react-native

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} />
</>
);
};

Related

Unable to pass a param when navigation to a different tab

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.

Set title in createStackNavigator onPress

I am making react native app. I have button and onPress i want to send headerTitle to createStackNavigator but i have some errors. I am sending title with setParams and in createStackNavigator i get it with getParam.
Why it is not working how is correct?
Code:
// page.js
<TouchableOpacity
onPress={() => navigate('Page2', {
this.props.navigation.setParams({Title: 'Title'});
})}>
// createStackNavigator
export default createStackNavigator(
{
Main: {
screen: Page1,
},
Page2: {
screen: Page2,
navigationOptions: ({ navigation }) => ({
headerTitle: navigation.state.getParam('Title', 'Default Title'),
}),
},
},
{
initialRouteName: 'Main',
}
);
The problem appears to be occurring in the operating order of the app.
Because the value is already obtained before the value is set, the value must be null or undefind, which is the value before the setting.
Try using it as a global function.
globalScreen
let TITLE = "defaultTitle"
function setT(data){
TITLE = data;
}
function getT() {
return TITLE;
}
export { setT, getT }
Usage
// page.js
import {setT } from "globalScreen"
<TouchableOpacity
onPress={() => {
setT("page2");
navigate('Page2'); }}>
// createStackNavigator
import {getT } from "globalScreen"
export default createStackNavigator(
{
Main: {
screen: Page1,
},
Page2: {
screen: Page2,
navigationOptions: ({ navigation }) => ({
headerTitle: getT(),
}),
},
},
{
initialRouteName: 'Main',
}
);

I have a problem in my code when updating react-navigation v2 to v3

I want to update the react-navigation library V2 to V3 and change part of my code thinking that there would not be any problems but it turns out that I have problems creating createStackNavigator with a screen of type createDrawerNavigator and that in turn contains createBottomTabNavigator.
my code that works with the previous version was:
export const createRootNavigator = (signedIn = false) => {
const commonNavigationOptions = {
headerStyle: {
shadowColor: 'transparent',
elevation: 0
},
headerTintColor: DEFAULT_THEME.topaz
};
const SignedIn = createStackNavigator(
{
Home: {
screen: Drawer('Home'),
navigationOptions: () => ({
headerStyle: {
height: 0
},
header: getSafeArea(DEFAULT_THEME.backgrouncolorHomeSafeArea)
})
},
Cards: {
screen: Tabs('Cards'),
navigationOptions: () => ({
headerStyle: {
height: 0
}
})
},
);
const SignedOut = createStackNavigator(
{
SignIn: {
screen: LoginContainer,
navigationOptions: () => ({
headerStyle: {
height: 0
},
header: getSafeArea(DEFAULT_THEME.dark)
})
},
SelectableCardsList: { screen: SelectableCardsListComponent },
);
return createSwitchNavigator(
{
SignedIn: { screen: SignedIn },
SignedOut: { screen: SignedOut }
},
{
initialRouteName: signedIn ? 'SignedIn' : 'SignedOut'
}
);
};
const Drawer = (initialRoute) => createDrawerNavigator(
{
Home: { screen: Tabs('Home') },
{
initialRouteName: initialRoute,
contentComponent: CustomDrawerComponent
}
);
const Tabs = (initialRouteName) => createBottomTabNavigator(
{
Home: {
screen: HomeContainer,
navigationOptions: {
tabBarLabel: I18n.t('tabs.me')
}
},
Home2: {
screen: Home2,
navigationOptions: {
tabBarLabel: I18n.t('tabs.credentials')
}
},
{
initialRouteName: initialRouteName,
tabBarComponent: ({ navigation }) => <CustomBottomBarComponent navigation={navigation} navigationState={navigation['state']} />,
tabBarOptions: {
style: {
backgroundColor: 'white'
}
}
}
);
try this solution with react-navigation V3 and send me an error
I try the following:
encapsulate createSwitchNavigator in createAppContainer and separate (SignedOut and SignedOut) createStackNavigator out of createSwitchNavigator, the rest is still the same.
export const createRootNavigator = (signedIn = false) => createAppContainer(createSwitchNavigator(
{
SignedIn: { screen: SignedIn },
SignedOut: { screen: SignedOut }
},
{
initialRouteName: signedIn ? 'SignedIn' : 'SignedOut'
}
));
I get the following error: The component for route 'Home' must be a react component. For Example
import MyScreen from './MyScreen';
...
Home : MyScreen,
}
you can also use a navigator:
The problem is located in this part:
const SignedIn = createStackNavigator(
{
Home: {
screen: Drawer,
Also try to change Drawer for any component (a component with a blank screen) and this works, but I can not insert the Tabs in the Drawer.
Thank you very much for your help.

How to disable the drawer from react navigation for a certain screen

I've seen a lot of stack overflow articles that suggest on how to do this however I tried all of them and none of them seem to work for my case.
my target:
to be able to disable the drawer from all of my screens except my JobFeedScreen.
What I already did:
drawerLockMode: 'locked-closed, drawerLockMode: 'locked-open'
I also tried to put it on the screen itself using
static navigationOptions = ({ navigation }) => {
const { state } = navigation;
const {} = state;
return {
header: null,
drawerLockMode: 'locked-closed' ( or drawerLockMode: 'locked-open')
};
}
here are my codes
for my drawer
AppNavigation.js
//DRAWER NAVIGATOR
const DrawerNav = createDrawerNavigator({
JobFeed: {
screen: JobFeedScreenStack,
navigationOptions: ({navigation})=>({
drawerLabel: 'Job Feed',
drawerIcon: ({ tintColor }) => (
<SimpleLineIcons name="briefcase" size={ Metrics.icons.tiny } color={Colors.heavyGray} />
)
})
},
NotificationScreen: {
screen: NotificationScreenStack,
navigationOptions: {
drawerLabel: 'Notifications',
drawerIcon: ({ tintColor }) => (
<Entypo name = "notification" size = {15} color = {Colors.heavyGray} tintColor={Colors.white}/> )
}
},
ApplicationsFeed: {
screen: ApplicationScreenStack,
navigationOptions: {
drawerLabel: 'Applications',
drawerIcon: ({ tintColor }) => (
<Foundation name = "clipboard-notes" size = {15} color = {Colors.heavyGray} tintColor={Colors.white}/> )
}
},
},
{
initialRouteName: 'JobFeed',
drawerPosition: 'left',
contentComponent: CustomDrawerComponent,
drawerType: 'slide',
drawerLockMode: 'locked-closed',
});
other codes in AppNavigation.js:
// Manifest of possible screens
const AuthStackNavigation = createStackNavigator({
LaunchScreen: {
screen: LaunchScreen,
},
JobFeedScreen: {
screen: JobFeedScreen,
},
FilterScreen: {
screen: FilterScreen,
},
NotificationScreen: {
screen: NotificationScreen,
},
ApplicationScreen: {
screen: ApplicationScreen,
}
},
{
// Default config for all screens
initialRouteName: 'JobFeedScreen',
})
//JOB FEED SCREEN
const JobFeedScreenStack = createStackNavigator({
JobFeedScreen: {
screen: JobFeedScreen,
},
})
//LAUNCH SCREEN
const LaunchScreenStack = createStackNavigator({
LaunchScreen: LaunchScreen,
})
//NOTIFICATION SCREEN
const NotificationScreenStack = createStackNavigator({
NotificationScreen: NotificationScreen,
})
//APPLICATION SCREEN
const ApplicationScreenStack = createStackNavigator({
ApplicationScreen: ApplicationScreen,
})
//FILTER SCREEN
const FilterScreenStack = createStackNavigator({
FilterScreen: FilterScreen
})
// MAIN NAVIGATION
const MainNavigation = createSwitchNavigator({
DrawerNav: DrawerNav,
AuthStackNavigation: AuthStackNavigation,
})
export default createAppContainer(MainNavigation)

How can I change the header navigation title dynamically when switcing tabs

I have 2 tabs and I put inside in createStackNavigator
I am using
"react-navigation": "^2.0.1",
"react-native": "0.55.3",
const Cstack = createStackNavigator({
cstack: {
screen: Screen1,
}
},{
headerMode:'none'
});
const Dstack = createStackNavigator({
dstack: {
screen: Screen2,
},
},{
headerMode:'none'
});
const mytabnavigator= createTabNavigator({
Tab1: {
screen: Cstack,
navigationOptions: ({navigation}) => ({
headerTintColor: 'white',
tabBarIcon: ({focused, tintColor}) => {
return (
<IconIonicons
name='ios-cash'
type='ionicon'
color="#FFFFFF"
size={26}
/>
);
},
})
},
Tab2: {
screen: Dstack,
navigationOptions: ({navigation}) => ({
headerTintColor: 'white',
tabBarIcon: ({focused, tintColor}) => {
return (
<IconIonicons
name='ios-card'
type='ionicon'
color="#FFFFFF"
size={26}
/>
);
},
})
}
}, {
tabBarOptions: {
showIcon: true,
style: {
backgroundColor: '#3f51b5',
},
inactiveTintColor: '#FFFFFF',
activeTintColor: "#FFFFFF"
},
});
const StackTab = createStackNavigator({
stacktab: mytabnavigator,
navigationOptions: ({navigation}) => ({
title: 'Welcome'
})
});
My problem is that they both share the same title Welcome
how can I dynamically change the title when I switch to other tab example I will switch tabsettings then my title would be Settings.
If you are using react navigation <2 i.e ~1.5.* You can set it like this.
const Tabs = TabNavigator({
Tab1:{
screen: Tab1,
navigationOptions: ({navigation}) => {
return { title: "Tab 1 Heading", tabBarLabel:"Tab 1 "}
},
}
Tab2:{
screen: Tab2
navigationOptions: ({navigation}) => {
return { title: "Tab 2 Heading", tabBarLabel:"Tab 2 "}
}
}
})
const Stack = StackNavigator({
tabs: {
screen: Tabs
navigationOptions: ({navigation}) => {
return { title: "Stack"}
}
},
otherScreen: Page
})
I'm not sure why did they remove this feature, when you try the same it won't work on the latest react-navigation. Now title object key is used for fallback it seems.
This may be helpful some users. If you wish you can try downgrading also.
I have the Upgraded the React Navigation to latest today for my project I think this way will be useful to someone
const Tabs = TabNavigator({
Tab1:{
screen: Tab1,
navigationOptions: ({navigation}) => {
return { tabBarLabel:"Tab 1 "}
}},
Tab2:{
screen: Tab2
navigationOptions: ({navigation}) => {
return { tabBarLabel:"Tab 2 "}
}}
});
Tabs.navigationOptions = ({navigation})=>{
const { routeName } = navigation.state.routes[navigation.state.index]; //This gives current route
switch(routeName){
case "Tab1":
headerTitle="Tab 1";
break;
case "Tab1":
headerTitle="Tab 1";
break;
}
return {
headerTitle: headerTitle
}
}
I had the same problem and I couldn't find anything but think I may have figured out a solution.
I added a navigationOptions callback for the screen -
const RootStack = createStackNavigator({
HomeScreen: {
screen: CustomHome,
navigationOptions: ({navigation}) => {
if(navigation && navigation.state && navigation.state.params && navigation.state.params.title) {
return {title: navigation.state.params.title}
}
}
},
InputScreen: {
screen: CustomInput,
navigationOptions: ({navigation}) => {
return {title: navigation.state.params.title}
}
}
})
and in my components in the constructor, I am calling this to update the header name
props.navigation.setParams({title: props.navigation.state.params.input.name})
Hope this helps.
You can set the header title manually in every single screen by making use of navigationOptions. Example:
class TabSettingsScreen extends React.Component {
static navigationOptions = ({navigation}) => ({
title: 'Settings'
})
render() {
return (... );
}
}
remove headerModer: 'none' in child navigators and give required title for screens
const Tstack = createStackNavigator({
tabsettings: {
screen: tabsettings,
navigationOptions: {title : 'Settings'}
},
});
Remove title in mainStackNavigator
const StackTab = createStackNavigator(
{
stacktab: mytabnavigator
},
{
navigationOptions: {
header: null
}
}
);
use TabNavigator
import TabNavigator from 'react-navigation';
declare title for each pages separately
class Screen1 extends React.Component {
static navigationOptions = ({navigation}) => ({
title: 'Settings'
})
}
remove headerMode:'none'