React Native - Creating Navigator dynamically with React Navigation

Your TabStack file:

const CATEGORIES = {
  "Food": { screen: FoodStack },
  // ...
}

export default (screenNames) => {
  const screens = screenNames.reduce((total, name) => ({...total, [name]: CATEGORIES[name]}), {})
  const TabStack = TabNavigator(screens,
    {
        tabBarComponent : props => <CustomTabItems props={props}/>,
        tabBarPosition: 'top',
        animationEnabled : true,
        initialRouteName : 'Food',
        swipeEnabled: true,
        tabBarOptions : {

            scrollEnabled : true
        }
  })
  return TabStack
}

Your Root file:

import getTabStack from './TabStack'


class Root extends Component {

    state = {
      categoriesNames: null
    }

    componentWillMount() {
      // assuming result is ["Food", "Drink", ... ]
      Api.fetchCategories().then((result) => {
        this.setState({ categoriesNames: result })
      })
    }

    render() {
      const { categoriesNames } = this.state
      if (!categoriesNames) {
        return <SplashScreen />
      }
      const TabStack = getTabStack(categoriesNames)
      return (
        <Provider store={store} >
          <TabStack />
        </Provider>
      );
    }
  }

Here I would like to post a method for creating tab bar according to the data we fetched from some API etc programmatically.

Here we fetch the data from API in this example, this code from the top level component :

renderShopTab() {
        const { client } = this.props;
        try {
            const { categories } = client.readQuery({
                query: gql`
                {
                    categories{
                        id
                        name
                        products{
                            id
                            name
                            price
                            quantity
                        }
                    }
                }`
            })

            console.log("Categories  :" + categories);

            return (
                <ShopCreator categories={categories} />
            )

        } catch (error) {
            console.log("Error occured creating the categories due to the : " + error);

            return (
                <View>
                    <Text>
                        Loading...
                    </Text>
                </View>
            )

        }

    }

This code snippet is from creator of the tab bar dynamically :

export const ShopCreator = ({ categories }) => {

    // This script will create a TabNavigator for categories and StackNavigators for each member of the categories !

    let categoryStack = {};

    let routes = {};


    categories.forEach((category) => {

        if (category.products.length > 0) {

            const { catname } = category.name;

            if (category.name != undefined) {

                routes[category.name] = {
                    screen: StackNavigator({
                        'isim': {
                            screen: ProductPage
                        }
                    },{
                        headerMode : 'none',
                        initialRouteParams : {
                            categoryName : category.name,
                            products : category.products
                        }
                    })
                }
            }
            
        } else {

            console.log("This category has no products !");

        }

    })

    console.log("OHA : " + JSON.stringify(routes));

    const ShopCatTabNav = TabNavigator(routes, {
        tabBarPosition: 'top',
        tabBarComponent: props => <TabMenuItems props={props} />
    })

    return <ShopCatTabNav />

}

As last , I will show you customized tab navigation bar I built :

const TabMenuItems = ({props}) => {

    const { activeTintColor, tab, tabbar, tabText, inactiveTintColor } = styles;
    const { index } = props.navigation.state;
    return(
        <View>
        <ScrollView contentContainerStyle={{ flex : 1 }} horizontal showsHorizontalScrollIndicator={false} style={{backgroundColor : '#FFAEB9'}}>
        {
            props.navigation.state.routes.length ? (
                props.navigation.state.routes.map((route,number)=>{
                    const focused = ( index === number ) ? '#1874CD' : '#FF6A6A';
                    const tintColor = focused ? activeTintColor : inactiveTintColor;
                    return (
                        <TouchableWithoutFeedback
                            key={route.key}
                            onPress={() => {
                                props.jumpToIndex(number)
                            }}
                            delayPressIn={0}
                            >
                            <View style={{marginLeft : 20, marginTop : height / 40, shadowOpacity : 25, alignSelf : 'flex-start' }}>
                                <Text style={{borderRadius : 5, fontWeight : 'bold', borderWidth :2, paddingTop : 5,color : 'white', height : height/18, width : width/5,textAlign : 'center', backgroundColor : focused, borderStyle: 'dashed',borderColor : '#CD2626'}}>
                                {props.getLabel({route, number})}
                                </Text>
                            </View>
                        </TouchableWithoutFeedback>
                    )
                })
            ) : null
        }
    </ScrollView>
    </View>
    )
}

export default TabMenuItems;