6

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 Answers 4

7

The problem lies in your component import statement.

Instead of

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

Type

import HeaderButton from '../components/CustomHeaderButton';
Sign up to request clarification or add additional context in comments.

Comments

3

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

Comments

2

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

1 Comment

IconComponent={Ionicons} -> can i use multiple icon library inside IconComponent, so that i use different icon name from different library, IconComponent={Ionicons | Fontawesome} something like this
0

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'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.