I am using the tabnavigator (createbottomBottomTabNavigator) and need help with the bage count using redux.
You can always create your custom component, in this case, the tab item (<TabBarItem />
).
I have created a simple demo, here is the snack link: https://snack.expo.io/@abranhe/tab-badge-count-redux
In this example, you have 3 pages/tabs (apps, navigation, and profile) so you need to manage the notification counter of every one of them. So we start by creating the component, I am using Native Base to have pre-built components. Also, we have the following initial state.
export default {
apps: {
notificationCount: 7,
},
navigation: {
notificationCount: 0,
},
profile: {
notificationCount: 3,
},
};
TabBarItem.js
import React from 'react';
import { connect } from 'react-redux';
import { View, StyleSheet } from 'react-native';
import { Badge, Button, Icon, Text } from 'native-base';
const renderBadge = ({ badgeProps, counter }) => (
<Badge {...badgeProps} style={styles.badge}>
<Text style={styles.notificationText}>{counter}</Text>
</Badge>
);
function TabBarItem({ notificationCount, badgeProps, icon, label, color }) {
let counter = 0;
switch (icon) {
case 'apps':
counter = notificationCount.apps;
break;
case 'navigate':
counter = notificationCount.navigation;
break;
case 'person':
counter = notificationCount.profile;
break;
default:
counter = 0;
}
return (
<View style={styles.container}>
{counter > 0 && renderBadge({ counter, badgeProps })}
<View style={styles.iconContainer}>
<Icon name={icon} style={{ color }} />
<Text style={{ color, ...styles.label }}>{label}</Text>
</View>
</View>
);
}
const styles = ....;
const mapStateToProps = state => ({
notificationCount: {
apps: state.apps.notificationCount,
navigation: state.navigation.notificationCount,
profile: state.profile.notificationCount,
},
});
export default connect(mapStateToProps)(TabBarItem);
This is just a work-around, and as you see I am creating a component connected to Redux and checking which tab should render depending on the icon name prop. If we have only one tab with notifications, only we needed to access the data on Redux, and automatically render.
We need to create a reducer to handle Increment and Decrement actions
export default function reducer(state = initialState, action = {}) {
switch (action.type) {
case 'APPS.INCREMENT':
return {
...state,
apps: {
...state.apps,
notificationCount: state.apps.notificationCount + 1,
},
};
case 'APPS.DECREMENT':
return {
...state,
apps: {
...state.apps,
notificationCount: state.apps.notificationCount - 1,
},
};
...
}
Well also we need to add the created component:
import React from 'react';
import { connect } from 'react-redux';
import { StyleSheet } from 'react-native';
import { Container, Content, H1, H3 } from 'native-base';
import NotificationCounter from '../components/NotificationCounter';
const Apps = ({ notificationCount, dispatch }) => (
<Container>
<Content contentContainerStyle={styles.container}>
<H1>Apps Page</H1>
<NotificationCounter
handleIncrement={() => dispatch({ type: 'APPS.INCREMENT' })}
handleDecrement={() => dispatch({ type: 'APPS.DECREMENT' })}
/>
<H3>Notification Count: {notificationCount}</H3>
</Content>
</Container>
);
const styles = ...
const mapStateToProps = state => ({
notificationCount: state.apps.notificationCount,
});
export default connect(mapStateToProps)(Apps);
We are using dispatch({ type: 'APPS.INCREMENT' })
to trigger the action that increments the notifcations for the apps tab.
The <NotificationCounter />
component code:
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { Button, Text } from 'native-base';
export default ({ handleDecrement, handleIncrement }) => (
<View style={styles.container}>
<Button onPress={handleDecrement}>
<Text>Decrement</Text>
</Button>
<Button onPress={handleIncrement}>
<Text>Increment</Text>
</Button>
</View>
);
const styles = ...
There is custom way to do this using redux, you can make your custom component using the same :-
screen: NotificationScreen,
navigationOptions: {
tabBar: (state, acc) => ({
icon: ({ tintColor, focused }) => (
<BadgeTabIcon
iconName="notification"
size={26}
selected={focused}
/>
),
visible: (acc && acc.visible !== 'undefined') ? acc.visible : true,
}),
},
},
where,
export default connect(state => ({
notificationCount: state.notifications.count,
}))(({ dispatch, nav }) => (
<View>
<TabIcon {...props} />
{
props.notificationCount > 0 ?
<View style={{ position: 'absolute', right: 10, top: 5, backgroundColor: 'red', borderRadius: 9, width: 18, height: 18, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ color: 'white' }}>{props.notificationCount}</Text>
</View> : null
}
</View>
));
Read here more
Also, official tabnavigation in react native have the support for the same, you can read here more
I hope this helps...Thanks :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With