それは不可能だと私は比較的確信していますが、方法がないことを確認したいと思います。
問題のアプリは、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;
これを修正する方法についてのアイデアはありますか?
はい、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} />;
}
}
ルーターは静的な方法で割り当てられ、実行時に動的に構築されます。
私はこれが古いことを知っていますが、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,
}
)
これが私の解決策です。私は博覧会を使用しています。 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',
},
});