Icon is not displaying in react-navigation-header-buttons (React Native)

4.1k Views Asked by At

I am trying to add an icon to the headerRight using react-navigation-header-buttons library. But the title of the icon is displaying instead of the icon.

This is the code where icon should display.

import React, { useState, useLayoutEffect } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native'

import { MEALS } from '../data/DummyData';
import { HeaderButtons, Item } from 'react-navigation-header-buttons';
import { HeaderButton } from '../components/CustomHeaderButton';

const MealDetailScreen = props => {
    const mealId = props.route.params.mealId;
    const selectedMeal = MEALS.find(meal => meal.id == mealId);
    const [headerTitle, setHeaderTitle] = useState();

    useLayoutEffect(() => {
        setHeaderTitle(() => selectedMeal === undefined ? props.route.params.title : selectedMeal.title)
        props.navigation.setOptions({
            headerTitle: headerTitle,
            headerRight: () => (
                <HeaderButtons HeaderButtonComponent={HeaderButton}>
                    <Item
                        title="Favourite"
                        iconName="ios-star"
                        onPress={() => {
                            console.log('Mark as favorite!');
                        }}
                    />
                </HeaderButtons>
            )
        });
    }, [props.navigation, headerTitle]);


    return (
        <View>
            <Text>The Meal Detail Screen!</Text>
            <Text>{selectedMeal.title}</Text>
            <Button title="Go Back to Categories!" onPress={() => {
                props.navigation.popToTop();
            }} />
        </View>
    )
}

const styles = StyleSheet.create({
});

export default MealDetailScreen;

This is the custom component for the header button.

import React from 'react';
import { Platform } from 'react-native';
import { HeaderButton } from 'react-navigation-header-buttons';
import { Ionicons } from '@expo/vector-icons';

import Colors from '../constants/Colors';

const CustomHeaderButton = props => {
    return (
        <HeaderButton
            {...props}
            IconComponent={Ionicons}
            iconSize={23}
            color={Platform.OS === 'android' ? 'white' : Colors.primaryColor}
        />);
}

export default CustomHeaderButton;

Only the title in the is displaying at the headerRight.

<Item
  title="Favourite"
  iconName="ios-star"
  onPress={() => {
  console.log('Mark as favorite!');
  }}
/>

React Native version: 5 react-navigation-header-buttons version: 3.0.5

4

There are 4 best solutions below

0
On

I solved the same problem with 2 changes:

  1. Instead of :
import { HeaderButton } from '../components/CustomHeaderButton'; 

Typed :

import HeaderButton from '../components/HeaderButton';
  1. I returned < HeaderButton > with arrow function and set it in headerRight as a variable headerRightButton :
MealDetailScreen.navigationOptions = (navigationData) => {
    const mealId = navigationData.navigation.getParam('mealId');
    const selectedMeal = MEALS.find(meal => meal.id === mealId);
    const headerRightButton = () => {
        return (
            <HeaderButtons HeaderButtonComponent={HeaderButton}>
                            <Item 
                                title= 'Favorite'
                                iconName="ios-star"
                                onPress= {() => {
                                    console.log('Added to favorites');
                                }}
                            />
                            <Item 
                                title= 'Favorite'
                                iconName= "ios-star-outline"
                                onPress= {() => {
                                    console.log('Added to favorites2');
                                }}
                            /> 
                      </HeaderButtons>
        );
    };
    return {
            headerTitle: selectedMeal.title,
            headerRight: (headerRightButton)
        };
};
    

1
On

I found in the example given, the IconComponent is (for whatever reason) not being passed down into Item. Since IconComponent is undefined, a Text component is used instead. That logic can be seen here.

The way I approached this is to create a custom component that would return the HeaderButtons instead of HeaderButton:

import React from 'react';
import { Ionicons } from '@expo/vector-icons';
import Colors from '../constants/colors';
import { Platform } from 'react-native';
import { HeaderButtons, HeaderButton } from 'react-navigation-header-buttons';

const CustomHeaderButton = (props) => (
  <HeaderButton
    IconComponent={Ionicons}
    iconSize={23}
    color={Platform.OS === 'android' ? 'white' : Colors.primaryColor}
    {...props}
  />
);

export const CustomHeaderButtons = (props) => {
  return <HeaderButtons HeaderButtonComponent={CustomHeaderButton} {...props} />;
};
export { Item } from 'react-navigation-header-buttons';

Now you can use it like this:

import { CustomHeaderButtons, Item } from '../components/HeaderButton';
...
MealDetailScreen.navigationOptions = navigationData => {
  const mealId = navigationData.navigation.getParam('mealId');
  const selectedMeal = MEALS.find(meal => meal.id === mealId);
  return {
    headerTitle: selectedMeal.title,
    headerRight: () => (
      <CustomHeaderButtons>
        <Item
          title='Favorite'
          iconName='ios-star'
          onPress={() => { console.log('Marked as favorite!') }}
        />
      </CustomHeaderButtons>
    )
  };
};
0
On

The problem lies in your component import statement.

Instead of

import { HeaderButton } from '../components/CustomHeaderButton';

Type

import HeaderButton from '../components/CustomHeaderButton';
0
On

This could be problem with background color of your header.

My Case: Header button appeared in Android but not in iOS(iPhone).

Resolution: Change below line to apply background independent of platform

From

color={Platform.OS === 'android' ? 'white' : Colors.primaryColor}

to

color='white'