web-dev-qa-db-ja.com

動的タブを使用したTabNavigatorの作成

それは不可能だと私は比較的確信していますが、方法がないことを確認したいと思います。

問題のアプリは、AppNavigator StackNavigatorで始まります。

export const AppNavigator = StackNavigator({
    Login: {
        screen: Login,
        navigationOptions: ({navigation}) => ({
            title: 'Aanmelden',
            params: {
                nuke: navigation.state.params && !!navigation.state.params.nuke,
            },
        }),
    },
    Main: {
        screen: DynamicTabBar,
        navigationOptions: ({navigation}) => ({
            title: 'Follow-up',
        }),
    },
}, {
    mode: 'modal',
    headerMode: 'none',
});

export class AppWithNavigationState extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        return <AppNavigator navigation={addNavigationHelpers({ dispatch: this.props.dispatch, state: this.props.navigationReducer })} />
    }
}

AppWithNavigationState.propTypes = {
    dispatch: React.PropTypes.func.isRequired,
    navigationReducer: React.PropTypes.object.isRequired,
};

const mapStateToProps = state => ({
    navigationReducer: state.navigationReducer,
});

export default connect(mapStateToProps)(AppWithNavigationState);

これまでのところ、ユーザーがログインするまで(つまり、DynamicTabBarからLoginに移動するまで)、Mainを「レンダリング」しないでください。

これが理由です

const Tabs = TabNavigator({
        Start: {
            screen: UserStackNavigator,
            navigationOptions: {
                tabBarIcon: (<Icon
                    type="font-awesome"
                    name="users"
                    color="#dddddd"
                    size={20}
                />),
            },
        },
        ...Account.User.CanEnter ? {
            ConditionalTab: {
                screen: ConditionalScreen,
                navigationOptions: {
                    tabBarIcon: (<Icon
                        type="font-awesome"
                        name="recycle"
                        color="#dddddd"
                        size={20}
                    />),
                },
            }} : {},
        Settings: {
            screen: Settings,
            navigationOptions: {
                tabBarIcon: (<Icon
                    type="font-awesome"
                    name="cog"
                    color="#dddddd"
                />),
            }
        }
    },{
        ...TabNavigator.Presets.AndroidTopTabs,
        tabBarPosition: "bottom",
        tabBarOptions: {
            activeTintColor: '#eaeb65',
            showIcon: true,
            showLabel: false,
            style: { backgroundColor: '#333' },
        }
    });

export default class DynamicTabBar extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return <Tabs navigation={this.props.navigation} />;
    }
}
DynamicTabBar.router = Tabs.router;

...Account.User.CanEnter ? {は、ユーザーがログインしてTabNavigatorが入力される前に、Accountがレンダリングされるため、常にfalseです。失敗した試み、それは継ぎ目です。

Tabs内にcomponentWillMountを入力したかったのですが、静的ルーターを設定できません:DynamicTabBar.router = Tabs.router;

これを修正する方法についてのアイデアはありますか?

8
DerpyNerd

はい、ssss!私は方法を見つけたと思います。解決策はおそらくデザインパターンに従っていませんが、これは私が思いついたものです:

export default class DynamicTabBar extends React.Component {
    static router = TabRouter({
        Start: {
            screen: UserStackNavigator,
            navigationOptions: {
                tabBarIcon: (<Icon
                    type="font-awesome"
                    name="users"
                    color="#dddddd"
                    size={20}
                />),
            },
        },
        ...Account.User.CanEnter ? {
            ConditionalTab: {
                screen: ConditionalScreen,
                navigationOptions: {
                    tabBarIcon: (<Icon
                        type="font-awesome"
                        name="recycle"
                        color="#dddddd"
                        size={20}
                    />),
                },
            }} : {},
        Settings: {
            screen: Settings,
            navigationOptions: {
                tabBarIcon: (<Icon
                    type="font-awesome"
                    name="cog"
                    color="#dddddd"
                />),
            }
        }
    },{
        ...TabNavigator.Presets.AndroidTopTabs,
        tabBarPosition: "bottom",
        tabBarOptions: {
            activeTintColor: '#eaeb65',
            showIcon: true,
            showLabel: false,
            style: { backgroundColor: '#333' },
        }
    });
    constructor(props) {
        super(props);
    }

    render() {
        const tabs = TabNavigator({
            Start: {
                screen: UserStackNavigator,
                navigationOptions: {
                    tabBarIcon: (<Icon
                        type="font-awesome"
                        name="users"
                        color="#dddddd"
                        size={20}
                    />),
                },
            },
            ...Account.User.CanEnter ? {
                ConditionalTab: {
                    screen: ConditionalScreen,
                    navigationOptions: {
                        tabBarIcon: (<Icon
                            type="font-awesome"
                            name="recycle"
                            color="#dddddd"
                            size={20}
                        />),
                    },
                }} : {},
            Settings: {
                screen: Settings,
                navigationOptions: {
                    tabBarIcon: (<Icon
                        type="font-awesome"
                        name="cog"
                        color="#dddddd"
                    />),
                }
            }
        },{
            ...TabNavigator.Presets.AndroidTopTabs,
            tabBarPosition: "bottom",
            tabBarOptions: {
                activeTintColor: '#eaeb65',
                showIcon: true,
                showLabel: false,
                style: { backgroundColor: '#333' },
            }
        });

        return <Tabs navigation={this.props.navigation} />;
    }
}

ルーターは静的な方法で割り当てられ、実行時に動的に構築されます。

4
DerpyNerd

私はこれが古いことを知っていますが、AFAICTは2019年にまだこれを行うための祝福された方法はありません。これが私が思いついた解決策であり、それはかなり簡単だと思います。

基本的に、現在のユーザーに基づいてボタンをレンダリングするかどうかを指定するカスタムtabBarComponentメソッドを使用してカスタムgetButtonComponentを指定します。ユーザーにナビゲーションアイテムが表示されない場合は、空のビューがレンダリングされ、ナビゲーションアイテムが非表示になります。

import { createBottomTabNavigator } from 'react-navigation'
import { BottomTabBar } from 'react-navigation-tabs'

class TabBar extends React.Component {
  render() {
    return (
      <BottomTabBar
        {...this.props}
        getButtonComponent={this.getButtonComponent}
      />
    )
  }

  getButtonComponent({ route }) {
    if (route.key === 'Other') {
      return () => <View /> // a view that doesn't render its children
    } else {
      return null // use the default nav button component
    }
  }
}

const AppNav = createBottomTabNavigator(
  {
    Home: HomeStack,
    Other: OtherScreen,
  },
  {
    tabBarComponent: TabBar,
  }
)
1
Tim Morgan

これが私の解決策です。私は博覧会を使用しています。 APIから取得するタブの動的な量とコンテンツが必要でした。

MainTabNavigator.js

import React from 'react';
import { Platform } from 'react-native';
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation';

import TabBarIcon from '../components/TabBarIcon';
import SettingsScreen from '../screens/SettingsScreen';
import {getBrowerScreen} from '../screens/BrowserScreen';


const SettingsStack = createStackNavigator({
  Settings: SettingsScreen,
});

SettingsStack.navigationOptions = {
  tabBarLabel: 'Settings',
  tabBarIcon: ({ focused }) => (
    <TabBarIcon
      focused={focused}
      name={Platform.OS === 'ios' ? 'ios-options' : 'md-options'}
    />
  ),
};

// Tab params that we will get from API
var tabParams = [
  {title: 'Tab 1', url: 'https://mycar.city', icon: 'md-pricetags'},
  {title: 'Tab 2', url: 'https://mycar.city', icon: 'ios-play-circle'},
  {title: 'Tab 3', url: 'https://mycar.city', icon: 'ios-phone-portrait'},
  {title: 'Tab 4', url: 'https://global-trend.info', icon: 'ios-phone-portrait'},
],
tabs = {};

for (var i=0; i<tabParams.length; i++) {
  const tab = tabParams[i];

  tabs['Tab' + (i + 1)] = createStackNavigator({
    Links: getBrowerScreen(tab.url),
  });

  tabs['Tab' + (i + 1)].navigationOptions = {
    tabBarLabel: tab.title,
    tabBarIcon: ({ focused }) => (
      <TabBarIcon
        focused={focused}
        name={tab.icon}
      />
    ),
  };
}

//Adding another kind of tab
tabs.SettingsStack = SettingsStack;

export default createBottomTabNavigator(tabs);

BrowserScreen.js

import React from 'react';
import { View, StyleSheet, WebView } from 'react-native';
import { ExpoLinksView } from '@expo/samples';

export function getBrowerScreen(url) {

  return class BrowserScreen extends React.Component {
    static navigationOptions = {
      header: null,
    };

    render() {
      return (
        <View style={styles.container}>
          <WebView
            source={{ uri: url }}
            style={{ width: '100%' }}
          />
        </View>
      );
    }
  };
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
});
0
Darkhan ZD