Can I connect createBottomTabNavigator to a redux store ? (React Native) - react-native

I have App.js looks like this
const TabNavigationStack = createBottomTabNavigator(
{
Dashboard: {
screen: Dashboard,
navigationOptions: {
tabBarLabel: () => null,
tabBarIcon: ({ tintColor }) => (
<Icon style={{ fontSize: 35, color: tintColor }} name='dashboard' type='MaterialIcons' />
)
}
},
Home: {
screen: OrderStack,
navigationOptions: {
tabBarLabel: () => null,
tabBarIcon: ({ tintColor }) => (
<Icon style={{ fontSize: 35, color: tintColor }} name='money' type='FontAwesome' />
)
}
},
Notification: {
screen: NotificationStack,
navigationOptions: {
tabBarLabel: () => null,
tabBarIcon: ({ tintColor }) => (
<IconBadge
MainElement={
<Icon style={{ fontSize: 35, color: tintColor }} name='notifications' type='MaterialIcons' />
}
IconBadgeStyle={{ zIndex: 1 }}
BadgeElement={
<Text style={{ color: '#FFFFFF', fontSize: 10 }}>0</Text>
}
Hidden={0}
/>
)
}
},
Profile: {
screen: Profile,
navigationOptions: {
tabBarLabel: () => null,
tabBarIcon: ({ tintColor }) => (
<Icon style={{ fontSize: 35, color: tintColor }} name='person' type='Ionicons' />
)
}
},
}, // router config
{
initialRouteName: 'Home',
order: ['Dashboard', 'Home', 'Notification', 'Profile'],
gesturesEnabled: false,
navigationOptions: {
header: null,
tabBarVisible: true
},
tabBarOptions: {
activeTintColor: COLOR.PRIMARY_COLOR,
inactiveTintColor: '#29333D'
}
}
)
const CombinedStack = createSwitchNavigator(
{
AuthStack: AuthStack,
TabNavigationStack: TabNavigationStack,
},
{
initialRouteName: 'AuthStack'
}
)
class App extends Component {
render() {
return (
<Root>
<Provider store={store}>
<CombinedStack ref={navigationRef => {
NavigationService.setTopLevelNavigator(navigationRef)
}
} />
</Provider>
</Root>
);
}
}
export default App;
Im planning to connect props in create navigator when the user login, I call an api which indicate the number of badge that connected in redux.
I already tried
const mapStateToProps = (state) => ({
badgeNumber: state.Notification
});
const mapDispatchToProps = (dispatch) => ({
dispatch: dispatch
})
const TabNavigationStack = connect(mapStateToProps)(createBottomTabNavigator)({....
but the I got error in props.
BTW I'm using react-navigation 2

Move your IconBadge component into a separate javascript file ... and connect that component to redux store
const AppIconWithBadge = ({ badgeNumber }) = {
//...
};
const mapStateToProps = (state) => ({ badgeNumber: state.Notification });
export default connect(mapStateToProps)(AppIconWithBadge);
tabBarIcon: ({ tintColor }) => (
<AppIconWithBadge style={{ fontSize: 35, color: tintColor }}
name='person' type='Ionicons' />
)

Related

React Native Navigation Title

Apparently simple problem: the Header Title in react Navigation
Navigator file with my Bottom Tabs
const BottomTabNavigator = createMaterialBottomTabNavigator(
{
ToFind: {
screen: TopBarNavigator,
navigationOptions: {
title: "Discover",
tabBarIcon: (tabInfo) => {
return (
<Ionicons
name="md-search"
size={25}
color={tabInfo.tintColor} //prende lo stesso colore di tintcolor giù
/>
);
},
tabBarColor: "#27ae60",
activeColor: "white",
},
},
....
const Navigator = createStackNavigator({
BottomTabNavigator,
Detail: DetailScreen, // not visible but I need the navigation
Item: ItemDisplay, // not visible but I need the navigation
});
Now I try to set the name into the page (at the bottom)
MapScreen.navigationOptions = (navData) => {
return {
headerTitle: "Map",
};
};
Doing this I have the Bottom Tabs styled as I want and navigation but I CAN'T change the header title (navigation title) but I always see BottomTabNavigator
It looks really trick or I'm mistaking somewhere?
Any Idea?
Thanks
createMaterialBottomTabNavigator does not have header bar by default, but createStackNavigator has.
You can do something like this.
import React from "React";
import { createAppContainer, createStackNavigator } from "react-navigation";
import { createMaterialBottomTabNavigator } from "react-navigation-material-bottom-tabs";
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Text>Home Screen</Text>
</View>
);
}
}
const Tab1 = createStackNavigator({
S1: {
screen: ToFind
}
});
const Tab2 = createStackNavigator({
S2: {
screen: ToFind
}
});
export default createAppContainer(
createBottomTabNavigator({
Tab1,
Tab2
}, {
//CUSTOM CONFIG
initialRouteName: 'Tab1',
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Tab1') {
iconName = 'icon1';
} else if (routeName === 'Tab2') {
iconName = 'icon2';
}
return <Icon name={iconName} size={24} color={tintColor} />;
<Ionicons
name={iconName}
size={25}
color={tabInfo.tintColor} //prende lo stesso colore di tintcolor giù
/>
},
}),
tabBarOptions: {
activeTintColor: 'white',
inactiveTintColor: 'black',
showLabel: false,
style: {
backgroundColor: '#27ae60',
borderTopWidth: 0,
borderTopColor: '#27ae60',
},
},
});
);
Try these steps. Hope to fix your problem.
Create Your Bottom Tab Navigator :
const BottomTabNavigator = createMaterialBottomTabNavigator(
{
PageOne: {
screen: PageOneComponent,
navigationOptions: {
tabBarIcon: ({ tintColor }) => <Feather name="airplay" size={26} color={tintColor} />,
tabBarLabel: null,
barStyle: { backgroundColor: 'white', elevation: 0, }
},
},
PageTwo: {
screen: PageTwoComponent,
navigationOptions: {
tabBarIcon: ({ tintColor }) => <Feather name="search" size={25} color={tintColor}/>,
tabBarLabel: null,
barStyle: { backgroundColor: 'white', elevation: 0, }
}
},
MapViewLink: {
screen: MapView,
navigationOptions: {
tabBarIcon: <Feather name="map-pin" size={25} color={'green'} />,
tabBarOnPress: ({ navigation }) => {
navigation.navigate('MapView');
},
tabBarLabel: null
}
},
},
{
initialRouteName: 'PageOne',
activeColor: 'orange',
inactiveColor: 'grey',
labeled: false,
barStyle: { backgroundColor: 'white', elevation: 0, borderTopWidth: 1, borderTopColor: '#efefef' },
}
);
Create your StackNavigator and export the navigator
const StackNavigator = createStackNavigator({
// bottom tab navigator
BottomTabNavigator: {
screen: BottomTabNavigator,
navigationOptions: {
header: null
}
},
// MapView Page
MapView: {
screen: MapView,
navigationOptions: ({ navigation }) => ({
title: 'Hello World'
})
},
}, {
defaultNavigationOptions: ({navigation}) => ({
headerTitleAlign: 'center',
cardStyle: { backgroundColor: '#FFFFFF' },
headerTitleStyle: {
// the default styles you want to apply to header title
},
});
export default createAppContainer(StackNavigator);
In the end, put the navigator inside the main project file. e.g App.js

how can I use constructor method with react navigation v3?

I need to use state on my App.js code but react-navigation v3 don't use class so I can't define the constructor method.
Is there any other way so I can use state?
I tried to use a boolean javascript variable but it didn't help.
I use StackNavigator, drawer navigator and DrawerNavigator and BottomTabNavigator like this
const TabAppNavigator = createBottomTabNavigator({
Posts: {
screen: PostsScreen,
navigationOptions: {
tabBarLabel: 'Posts',
tabBarIcon: ({ tintColor }) => (<Icon name="md-home" color={tintColor} size={25} />)
}
},
Tools: {
screen: ToolsScreen,
navigationOptions: {
tabBarLabel: 'Tools',
tabBarIcon: ({ tintColor }) => (<Icon name="md-apps" color={tintColor} size={25} />)
}
},
Favourite: {
screen: FavouriteScreen,
navigationOptions: {
tabBarLabel: 'Favourite',
tabBarIcon: ({ tintColor }) => (<Icon name="md-heart" color={tintColor} size={25} />)
}
},
}, {
initialRouteName: 'Posts',
order: ['Posts', 'Tools', 'Favourite'],
tabBarOptions: {
activeTintColor: '#d94854',
inactiveTintColor: '#818181',
style: {
backgroundColor: '#fff',
borderTopColor: '#818181',
borderTopWidth: 1,
paddingBottom: 5,
paddingTop: 15,
},
labelStyle: {
fontSize: 13,
marginTop: 10,
},
},
navigationOptions: ({ navigation }) => {
return {
headerTitle: 'Growth Hack Toolkit',
headerTintColor: '#fff',
headerStyle: {
backgroundColor: '#d94854',
},
headerLeft: (
<Icon name="md-menu" color="#fff" size={25} style={{ paddingLeft: 15 }} onPress={() => navigation.openDrawer()} />
),
headerRight: (
<Icon name="md-search" color="#fff" size={25} style={{ paddingRight: 15 }} onPress={() => search()} />
)
}
}
}
)
const PostsStackAppNavigator = createStackNavigator({
TabAppNavigator: TabAppNavigator,
Posts: { screen: PostsScreen },
Post: { screen: PostScreen }
})
const ToolsStackAppNavigator = createStackNavigator({
TabAppNavigator: TabAppNavigator,
Tools: { screen: ToolsScreen },
Tool: { screen: ToolScreen },
ToolList: { screen: ToolListScreen },
Web: { screen: WebScreen },
Mobile: { screen: MobileScreen },
})
const DrawerAppNavigator = createDrawerNavigator({
Posts: { screen: PostsStackAppNavigator },
Tools: { screen: ToolsStackAppNavigator },
About: { screen: AboutScreen },
}, {
contentComponent: SideMenu,
drawerWidth: 250,
})
const App = createAppContainer(DrawerAppNavigator);
export default App;
I want to change my header view based on my state
basically, I have a default header (the same header for all tab screens) that contains a title, menu icon to open the drawer navigation and search icon to start searching
what I need to do is that when search icon is pressed I will change my state to show the instead of the title and when close icon is pressed I will change the state to show my default header again.
after spending so much time searching for a solution or a workaround, the answer is: I cannot.
It is not possible to have state in a functional component. So I have to use react navigation v2 instead of v3 as it is implemented as class-based component.
These links could help to understand:
difference between functional and class-based React components
React State without Constructor

React Navigation: Is it possible to navigate to the same screen from different stackNavigators?

I'm coding an app that uses react-navigation. My app has a bottom TabNavigator in which each tab consists of a stackNavigator, like so:
Routes.js:
const FirstStack = createStackNavigator({
First: {
screen: FirstScreen,
navigationOptions: {
header: props => <AppToolbar />
}
}
});
const SecondStack = createStackNavigator({
Second: {
screen: SecondScreen,
navigationOptions: {
header: props => <AppToolbar />
}
}
});
const ThirdStack = createStackNavigator({
Third: {
screen: ThirdScreen,
navigationOptions: {
header: props => <AppToolbar />
}
}
});
const FourthStack = createStackNavigator({
Fourth: {
screen: FourthScreen,
navigationOptions: {
header: props => <AppToolbar />
}
}
});
const FifthStack = createStackNavigator({
Fifth: {
screen: FifthScreen,
navigationOptions: {
header: props => <AppToolbar />
}
}
});
export const AppStack = createBottomTabNavigator(
{
First: {
screen: FirstStack,
navigationOptions: {
title: "First",
tabBarLabel: "First",
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-home" color={tintColor} size={24} />
)
}
},
Second: {
screen: SecondStack,
navigationOptions: {
title: "Second",
tabBarLabel: "Second",
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-clock" color={tintColor} size={24} />
)
}
},
Third: {
screen: ThirdStack,
navigationOptions: {
title: "Third",
tabBarLabel: "Third",
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-fitness" color={tintColor} size={24} />
)
}
},
Fourth: {
screen: FourthStack,
navigationOptions: {
title: "Fourth",
tabBarLabel: "Fourth",
tabBarIcon: ({ tintColor }) => (
<Icon
name="ios-cloud-download"
color={tintColor}
size={24}
/>
)
}
},
Fifth: {
screen: FifthStack,
navigationOptions: {
title: "Fifth",
tabBarLabel: "Fifth",
tabBarIcon: ({ tintColor }) => (
<Icon name="ios-person" color={tintColor} size={24} />
)
}
}
},
{
initialRouteName: "First",
order: ["First", "Second", "Third", "Fourth", "Fifth"],
tabBarOptions: {
activeTintColor: "white",
inactiveTintColor: "grey",
style: {
backgroundColor: "#121212",
borderTopColor: "#303030"
}
}
}
);
Each stackNavigator inside the tabs in the tabNavigator has its own header so that I can customize the header for each tab, but all headers have a button which should navigate to the profile screen (in this example its the contact icon).
AppToolbar.js:
const appToolbar = props => {
return (
<View style={styles.toolbar}>
<Text style={styles.toolbarTitle}>Title</Text>
<TouchableOpacity onPress={...}>
<Icon
name="ios-contact"
color="grey"
size={30}
style={{ padding: 0, margin: 0, marginRight: 10 }}
/>
</TouchableOpacity>
</View>
);
};
What I want to do is that by pressing the contact icon the app should navigate to the profile screen, what I don't know is if its possible to define like a global route thats accesible from everywhere, Or do I have to add the profile screen to all the stackNavigators so that it is accesible from every screen in every stack?
Thanks in advance!
Found the answer here https://stackoverflow.com/a/50701940/1276438
Use a stackNavigator with the profile stack and the tabNavigator as children, making the tabNavigator the default route.

open pupop when select a tab react native

i'm new to react native and i want to have a tabNavigator that when 'Other' tab is selected a popup shows up . its my code but it don't recognize 'this' in 'ModalExample' class.
any help would be appreciated.
export const Tabs = TabNavigator({
Notifications: {
screen: Notifications,
navigationOptions: {
tabBarIcon: ({ tintColor }) => <Icon name="access-alarms" size={25} color={tintColor} />
},
},
Home: {
screen: Home,
navigationOptions: {
tabBarIcon: ({ tintColor }) => <Icon name="home" size={25} color={tintColor} />
},
},
Other: {
screen: ModalExample,
navigationOptions: {
tabBarIcon: ({ tintColor }) => <Icon name="more" size={25} color={tintColor} />
},
},
},
{
tabBarOptions: {
showIcon: true,
showLabel: false,
scrollEnabled: false
},
tabBarPosition: 'bottom',
});
and its other class:
export default class ModalExample extends Component {
constructor(props){
super(props);
this.popupDialog.show();
}
render() {
return (
<View>
<PopupDialog
ref={(popupDialog) => { this.popupDialog = popupDialog; }}
>
<View>
<Text>Hello</Text>
</View>
</PopupDialog>
</View>
);
}
}
I didn't understand how you are using <PopupDialog/>. But i think this link can help you with your requirement.

Icons/Images do not display with TabBarBottom in React Native

I've pretty much taken the sample code from the TabNavigator documentation and the icon's/images simply don't appear on iOS or Android. Even the label override doesn't seem to take effect. What am I doing wrong?
Here's the link to the docs I've been using:
https://reactnavigation.org/docs/navigators/tab
Here's my code:
class MyHomeScreen extends React.Component {
static navigationOptions = {
tabBarLabel: 'Not displayed',
// Note: By default the icon is only shown on iOS. Search the showIcon option below.
tabBarIcon: ({ tintColor }) => (
<Image
source={require('./chats-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.navigate('Notifications')}
title="Go to notifications"
/>
);
}
}
class MyNotificationsScreen extends React.Component {
static navigationOptions = {
tabBarLabel: 'Notifications',
tabBarIcon: ({ tintColor }) => (
<Image
source={require('./notif-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.goBack()}
title="Go back home"
/>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 26,
height: 26,
},
});
const MyApp = TabNavigator({
Displayed: {
screen: MyHomeScreen,
},
Notifications: {
screen: MyNotificationsScreen,
},
}, {
tabBarOptions: {
activeTintColor: '#e91e63',
},
});
Alright, I finally figured it out after wanting to slam my face into the keyboard.
The title and tab bar icon is actually a different structure to what's inside the docs.
const MyApp = TabNavigator({
Displayed: {
screen: MyHomeScreen,
navigationOptions: {
title: 'Favorites',
tabBar: {
icon: ({tintColor}) => (<Image
source={require('./chats-icon.png')}
style={{width: 26, height: 26, tintColor: tintColor}}
/>)
},
},
},
...
or
class MyHomeScreen extends React.Component {
static navigationOptions = {
title: 'Foo Bar',
tabBar: {
icon: ({ tintColor }) => (
<Image
source={require('./chats-icon.png')}
style={{width: 26, height: 26, tintColor: tintColor}}
/>
),
}
};
...
As for react-navigation-tabs v2.6.2 is it now as described in the doc.
To update the old example, you have to replace tabBar: { icon: ... } by tabBarIcon: ...
e.g.
class MyHomeScreen extends React.Component {
static navigationOptions = {
title: 'Foo Bar',
tabBarIcon: ({ tintColor }) => (
<Image
source={require('./chats-icon.png')}
style={{width: 26, height: 26, tintColor: tintColor}}
/>
)
};
I was searching for answers in stack overflow while answer was in documentation itself. For using images as icon in react-native bottom tab. This is according to current React Navigation 4.x.
const tabNavigator = createBottomTabNavigator({
Style: HomeScreen,
Location: LocationScreen,
},
{
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, horizontal, tintColor }) => {
const { routeName } = navigation.state;
if (routeName === 'Style') {
return <Image
source={require('./screens/assets/notifications.png')}
style={{ height: 25, width: 25, tintColor: tintColor }}
/>;
} else if (routeName === 'Location') {
return <Image
source={require('./screens/assets/location.png')}
style={{ height: 35, width: 35, tintColor: tintColor }}
/>;
}
},
}),
tabBarOptions: {
activeTintColor: 'tomato', //For changing tint colors
inactiveTintColor: 'gray',
},
}
),
You can find additional info here.
Got the same problem, but this solution didn't worked for me. Invalid Key 'tabBar' defined in navigation options...
Edit:
Got it working when I removed the tabBarOptions from my tab navigator.
instead used the activeTintColor and inactiveTintColor as the props of TabBarBottom.