简体   繁体   中英

React Native Navigation: Conditionally render tab bar badge not working?

I am trying to show a tab bar badge for my notifications tab. If a user has a notification, after writing the notification in the backend, I set a field for the user "hasNotifications" as true. Once I click on the notifications tab, I set "hasNotifications" to false.

Here is my implementation:

function renderBadge() {

  Firebase.firestore()
  .collection('users')
  .doc(Firebase.auth().currentUser.uid)
  .onSnapshot(function(doc) { 

      if (doc.data().hasNotifications) {
          console.log("true")
          return true
      }
      else {
          console.log("null")
          return null
      }
      
  })
}

 
//Bottom Tabs
function Tabs() {
  
  return (

    <Tab.Navigator
    initialRouteName="Home"
    tabBarOptions={{
      activeTintColor:"#FFFFFF",
      inactiveTintColor:"#696969",
      style: {
        backgroundColor: '#000000',
        borderTopColor: "transparent"
      },
    }}>

      <Tab.Screen 
        name="Notificaton" 
        component={Notification}
        options={{
          tabBarLabel: ' ',
          tabBarIcon: ({ color, size }) => (
            <Ionicons name="md-notifications" size={size} color={color} />
          ),
          tabBarBadge: renderBadge() <----- Render red dot if true, no red dot if null

        }}
      />  

    </Tab.Navigator>
  );
}

The console logging shows me the listener is working, and returns true/null based on whether the user has notifications. But the tab bar badge does NOT show up. How can I fix this?

EDIT: Looks like when I set tabBarBadge: renderBadge() , the badge never shows up. When I set tabBarBadge: renderBadge , the badge always shows up. The listener is working fine, but this is not.

EDIT 2: I changed the function to const renderBadge = () => { , and it still doesn't work.

I know react (for browsers) better than react-native, but if the paradigm is the same, you should change the following aspects:

  • Instead of directly changing a variable in the function scope, make use of useState to hold the boolean value; change the value provided by its setter function
    • This will react allow to notice the change when it happens and make it -- react.
  • Your Firebase access is probably some kind of side-effect, so you should use useEffect , perhaps with Firebase.auth().currentUser.uid as a dependency.

The result could be similar to this:

function useNotificationsBadge() {
    const [hasNotifications, setHasNotifications] = useState(null);
    const userId = Firebase.auth().currentUser.uid;

    useEffect(
        () => Firebase.firestore()
            .collection('users')
            .doc(userId)
            .onSnapshot(function(doc) {
                const newHasNotifications = doc.data().hasNotifications ? true : null;
                setHasNotifications(newHasNotifications);
            }),
        [userId]
    );

    return hasNotifications;
}

In your component you can then write;

    ...
    const hasNotifications = useNotificationsBadge();
    ...

        tabBarBadge: hasNotifications

My personal recommendation would be to replace null by false in this snippet to make the API more clear.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM