繁体   English   中英

React Native - 使用 React Navigation 动态创建导航器

[英]React Native - Creating Navigator dynamically with React Navigation

我正在使用 React Native 构建一个移动应用程序,我正在使用 React Navigation 在我的应用程序中构建一个导航器。 React 导航为我提供了一种处理抽屉内嵌套 Tab 栏的好方法,该抽屉也位于 Stack Navigator 内。

问题是我需要指定组件,以便我可以将它们提供到选项卡栏中。 假设我们必须从 API 中获取一些类别,但我们不知道数据中有多少类别。 此外,我无法弄清楚即使我尝试在开始时获取数据,导航器和 redux 配置也会在开始时进行,这意味着应用程序必须知道这些选项卡导航器中的组件。 我无法弄清楚即使我从 API 获取数据,如何创建多个组件并同时停止应用程序配置。

下面的代码只是演示了我是如何实现标签栏的。 这段代码在 index.js 中有效,因为正如我之前提到的,应用程序必须知道 Navigator 中的组件。

 const TabStack = TabNavigator({ Food: { screen: FoodStack}, Drink : { screen: DrinkStack }, HealthCare : { screen: SnackProducts }, Snacks: { screen: SnackStack }, }, { tabBarComponent : props => <CustomTabItems props={props}/>, tabBarPosition: 'top', animationEnabled : true, initialRouteName : 'Food', swipeEnabled: true, tabBarOptions : { scrollEnabled : true } })

谢谢

这里是根代码

 import { AppRegistry } from 'react-native'; import React from 'react'; import { Text, Image, ScrollView, View, List, ListItem, TouchableWithoutFeedback } from 'react-native'; import { Icon, Avatar } from 'react-native-elements'; import { Provider, connect } from 'react-redux' import thunkMiddleware from 'redux-thunk' import { createStore, applyMiddleware, combineReducers } from 'redux'; import { addNavigationHelpers, StackNavigator, DrawerNavigator, DrawerItems, TabNavigator, TabView, TabBarTop, NavigationActions } from 'react-navigation'; // importing starting screen import StartingContainer from './src/containers/StartingScreen/StartingContainer'; // Menu Containers import MenuCredentials from './src/containers/MenuCredentials'; // Containers import LoginContainer from './src/containers/LoginContainer'; import PhoneNumberValidation from './src/containers/SubLoginContainers/PhoneNumberValidation'; import MainOrderContainer from './src/containers/OrderContainers/MainOrderContainer'; import MainCartContainer from './src/containers/CartContainers/MainCartContainer'; // Components // Login Components import SMSLogin from './src/containers/SubLoginContainers/SMSLogin'; // Profil Components import Profil from './src/components/ProfileComponents/Profile'; import AdressComponent from './src/components/ProfileComponents/AdressComponent'; import SettingsComponent from './src/components/ProfileComponents/SettingsComponent'; import creditCardComponent from './src/components/ProfileComponents/creditCardComponent'; // Reducers import initialReducer from './src/reducers/initialReducer'; import cartReducer from './src/reducers/cartReducer'; import starterReducer from './src/reducers/starterReducer'; // import tab bar containers import FoodProducts from './src/containers/TabBarContainers/FoodProducts'; import HealthProducts from './src/containers/TabBarContainers/HealthProducts'; import SnackProducts from './src/containers/TabBarContainers/SnackProducts'; // Building Navigation import MenuItem from './src/containers/MenuItemContainer/MenuItem'; import CustomTabItems from './src/containers/CustomTabItems'; import CustomSubTabItems from './src/containers/CustomSubTabItems'; import DrawerButton from './src/containers/DrawerButton'; // Tab Bar Navigation const ChocolateStack = TabNavigator({ Tadelle: { screen: MenuItem}, Milka: { screen: MenuItem}, }, { tabBarComponent : props => <CustomTabItems props={props}/>, tabBarPosition: 'top', animationEnabled : true, initialRouteName : 'Tadelle', swipeEnabled: true, tabBarOptions: { scrollEnabled: true }, }) const SnackStack = TabNavigator({ Çikolatalar: { screen: MenuItem}, Gofretler: { screen: MenuItem}, Krakerler: { screen: MenuItem}, Bisküviler: { screen: MenuItem}, Kuruyemişler: { screen: MenuItem}, }, { tabBarComponent : props => <CustomSubTabItems props={props}/>, tabBarPosition: 'top', animationEnabled : true, initialRouteName : 'Çikolatalar', swipeEnabled: true, tabBarOptions : { scrollEnabled : true } }) const DrinkStack = TabNavigator({ 'Gazlı İçecekler': { screen: MenuItem}, 'Soğuk Çaylar': { screen: MenuItem}, 'Alkol': { screen: MenuItem}, 'Süt Ürünleri': { screen: MenuItem}, 'Spor İçecekleri': { screen: MenuItem}, }, { tabBarComponent : props => <CustomSubTabItems props={props}/>, tabBarPosition: 'top', animationEnabled : true, initialRouteName : 'Alkol', swipeEnabled: true, tabBarOptions : { scrollEnabled : true } }) const FoodStack = TabNavigator({ Sandviç : { screen: MenuItem}, Çorba: { screen: MenuItem}, }, { tabBarComponent : props => <CustomSubTabItems props={props}/>, tabBarPosition: 'top', animationEnabled : true, initialRouteName : 'Sandviç', swipeEnabled: true, tabBarOptions : { scrollEnabled : true } }) const TabStack = TabNavigator({ Food: { screen: FoodStack}, Drink : { screen: DrinkStack }, Health : { screen: SnackProducts }, Snacks: { screen: SnackStack }, }, { tabBarComponent : props => <CustomTabItems props={props}/>, tabBarPosition: 'top', animationEnabled : true, initialRouteName : 'Food', swipeEnabled: true, tabBarOptions : { tabStyle : { width : 250 }, scrollEnabled : true } }) // cart navigation will be drawernavigator and drawerItems will be custom !! const CartNavigation = StackNavigator({ Cart: { screen: MainCartContainer, } }, { headerMode: 'float', navigationOptions: ({ navigation }) => ({ title: 'Sepet', headerLeft: <Icon name='arrow-back' color='#517fa4' onPress={() => navigation.navigate('drawerStack')} />, headerRight: <Icon name='payment' color='#517fa4' onPress={() => navigation.navigate('drawerStack')} /> }) } ) const DrawerStack = DrawerNavigator({ Sipariş: { screen: TabStack }, Profil: { screen: Profil , navigationOptions : ({ navigation }) => ({ title : 'Profilim', }) }, Adreslerim: { screen: AdressComponent, navigationOptions: ({ navigation }) => ({ title: 'Teslimat Adreslerim' }) }, Ayarlar: { screen: SettingsComponent } }, { drawerPosition: 'left', headerMode : 'none', navigationOptions: ({ navigation }) => ({ headerStyle: { backgroundColor: '#87CEFA' }, headerRight: <Icon name='shopping-cart' color='#517fa4' onPress={() => navigation.navigate('cartStack')} />, }), contentOptions: { inactiveTintColor: 'white', activeTintColor: 'purple', style: { marginTop: 80, marginLeft: 25, } }, contentComponent: props => <MenuCredentials {...props} /> }) const DrawerNavigation = StackNavigator({ DrawerStack: { screen: DrawerStack }}, { style : { leftDrawerWidth : 40 }, index : 0, navigationOptions : ({ navigation }) => ({ headerStyle: { backgroundColor: '#87CEFA' }, gesturesEnabled : false, headerRight : <Icon name='shopping-cart' color='#517fa4' onPress={() => navigation.navigate('cartStack')} />, headerLeft: <Icon name='menu' color='#517fa4' onPress={() => { console.log(navigation.state.routes[0]); navigation.navigate({ key : null, index : 0, action : [ navigation.navigate('DrawerToggle') ] }) }} /> }), initialRouteParams : { name : 'Welcome' } } ) const LoginStack = StackNavigator({ Login: { screen: LoginContainer, navigationOptions: ({ navigation }) => ({ title: ' GİZLİ UYGULAMA ! ' }) }, Ss: { screen: SMSLogin, navigationOptions: ({ navigation }) => ({ title: ' SMS ONAYI ' }) }, PhoneNumberValidation: { screen: PhoneNumberValidation, navigationOptions: ({ navigation }) => ({ title: 'Kaydolma' }) }, },{ headerMode : 'none', initialRouteName : 'Login' }) // IMPORTANT NOTE ***!!! // CARRY drawerStack to the PrimaryNavigator !! // CHANGE LoginContainer so that it will navigate to the drawerStack // NOT FROM ACTION BUT FROM COMPONENT INSIDE COMPONENTWILLUPDATE // BY CHANGING isAuth variable in initialReducer !! const PrimaryNavigator = StackNavigator({ loginStack: { screen: LoginStack }, cartStack: { screen: CartNavigation }, drawerStack: { screen: DrawerNavigation }, starter : { screen : StartingContainer } }, { headerMode: 'none', title: 'Main', initialRouteName : 'starter' } ) const navReducer = (state, action) => { const nextState = PrimaryNavigator.router.getStateForAction(action, state); // Simply return the original `state` if `nextState` is null or undefined. return nextState || state; }; // combining Reducers const AppReducer = combineReducers({ initialR: initialReducer, cartR: cartReducer, starterR : starterReducer, nav: navReducer }) // Creating redux store const store = createStore( AppReducer, applyMiddleware(thunkMiddleware) ) // Navigation initilizator to App class App extends React.Component { render() { return ( <PrimaryNavigator navigation={addNavigationHelpers({ dispatch: this.props.dispatch, state: this.props.nav })} /> ) } } const mapStateToProps = (state) => ({ nav: state.nav }) const AppWithNavigationState = connect(mapStateToProps)(App); class brilliantApp extends React.Component{ render(){ return( <Provider store={store}> < AppWithNavigationState /> </Provider> ) } } AppRegistry.registerComponent('brilliantApp', () => brilliantApp);

您的 TabStack 文件:

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
}

您的根文件:

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

在这里,我想发布一种根据我们以编程方式从某些 API 等获取的数据创建标签栏的方法。

在这里,我们从本示例中的 API 获取数据,此代码来自顶级组件:

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

此代码片段来自动态标签栏的创建者:

 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 /> }

最后,我将向您展示我构建的自定义标签导航栏:

 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;

这个问题已经发布了一段时间,但如果还有人在看这个。 我宁愿使用react-native-navigation而不是这个库。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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