How to add a custom component to createMaterialTopTabNavigator tab bar

It is not so difficult to create a custom tab bar component, below is a mimimised example of a custom tab bar I created for a project I am working on.

But in fact there is not so much to it, your tab bar component receives a navigation prop which holds the different routes you have set up in createMaterialTopTabNavigator. So you simply loop over those routes and display an tab bar item for each of them.

CustomTabBar.jsx

export default class CustomTabBar extends React.Component {

  render() {

    const {navigation} = this.props;    
    const routes = navigation.state.routes;

    return (
      <SafeAreaView style={{backgroundColor: 'blue'}}>
        <View style={styles.container}>
          {routes.map((route, index) => {
            return (
              <View style={styles.tabBarItem}>
                <CustomTabBarIcon
                  key={route.key}
                  routeName=route.routeName
                  onPress={() => this.navigationHandler(index)}
                  focused={navigation.state.index === index}
                  index={index}
                />
          </View>
            );
          }
        </View>
      </SafeAreaView>
    );
  }

  navigationHandler = (routeName) => {
    this.props.navigation.navigate(routeName);
  }
}

const styles = StyleSheet.create({

  container: {
    flexDirection: 'row',
    alignContent: 'center',
    height: 56,
    width: '100%',
    paddingHorizontal: 16,
    backgroundColor: 'blue',
  },
  tabBarItem: {
    flex: 1,
    alignItems: 'center'
  }
});

CustomTabBarItem.jsx

class CustomTabBarIcon extends React.PureComponent {

  render() {

    const {index, focused, routeName} = this.props;
    let icon = '';

    switch (index) {
      case 0: 
        icon = 'a';
        break;

      case 1:
        icon : 'b';
        break;

      case 2:
        icon = 'c';
        break;

      default: 
        iconName = 'a';
    }

    return (
      <TouchableWithoutFeedback
        onPress={() => this.onSelect(routeName)}
      >
        <View style={[styles.container, focused ? styles.active : styles.inactive]}> 
          <View style={styles.icon}>
            <Icon name={icon} color='white' size={24}/>
          </View>
          <Text style={styles.textStyle}>{routeName}</Text>
        </View>
      </TouchableWithoutFeedback>
    );
  }

  onSelect = (routeName) => {    
    this.props.onPress(routeName);
  }
}

const styles = StyleSheet.create({

  container: {
    flex: 1,
    alignItems: 'center'
  },
  active: {
    borderTopWidth: 3,
    borderColor: 'white'
  },
  inactive: {
    borderTopWidth: 3,
    borderColor: 'blue'  
  },
  textStyle: {
    color: 'white',
    fontSize: 13
  }
});

A very simple approach will be to use Fragment from react. It solves the problem.

import React, {Fragment} from 'react';

And your component return could look like this

return (
        <Fragment>
            <MyCustomHeader/>
            <MaterialTopTabBar/>
        </Fragment>

    )