(也在https://github.com/react-navigation/react-navigation/issues/4059#issuecomment-453100740中询问)
我已经用动态的TabNavigator替换了静态的TabNavigator,并且一切似乎正常。
但是,已按预期方式通过的道具不再以相同的方式通过。
任何想法如何解决这个问题?通过在静态解决方案中传递道具,或通过传递所需的道具(this.props.navigation)。
export default createDrawerNavigator({
Drawer: MainDrawerNavigator,
Main: MainTabNavigator
}, {
contentComponent: props => <Drawer {...props} />,
});
const ProfileStack = createStackNavigator({
Profile: {
screen: Profile,
navigationOptions: () => ({
title: 'Profile'
})
}
}, {
initialRouteName: 'Profile'
});
ProfileStack.navigationOptions = {
tabBarLabel: 'Profile',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name= 'md-person' />
)};
const MainTabNavigator = createBottomTabNavigator({
RequestStack,
ProfileStack
}, {
headerMode: 'none',
initialRouteName: ProfileStack
});
Profile
屏幕:import React from 'react';
import { View, TouchableOpacity } from 'react-native';
import { Container, Header, Content, Text
} from 'native-base';
export default class Profile extends React.Component {
static navigationOptions = {
header: null
};
constructor(props) {
super(props);
}
render() {
console.log('in Profile. this.props:');
console.log(this.props);
return (
<Container style={styles.container}>
<Header>
<TouchableOpacity
onPress={() => this.props.navigation.openDrawer()}>
<Icon name="md-more" />
</TouchableOpacity>
</Header>
<Content>
<Text>aaa</Text>
</Content>
</Container>
);
}
}
当我用下面的Dynamic替换上面的静态Tab Navigator时,this.props.navigation.openDrawer没有通过,因此未在“配置文件”中定义(配置文件不变,更改仅在底部选项卡中航海家)。
export default class DynamicTabNavigator extends React.Component {
constructor(props) {
super(props);
}
_tabNavigator() {
let tabs = {};
const a = 2;
if (a > 1) { // the actual line is obviously different, I am trying to simplify the example
tabs = { RequestStack, ManageStack, MessagesStack, ProfileStack };
} else {
tabs = { WorkStack, ManageStack, MessagesStack, ProfileStack };
}
console.log('in _tabNavigator. this.props.navigation:');
console.log(this.props.navigation);
return createBottomTabNavigator(tabs, {
headerMode: 'none',
});
}
render() {
const Tabs = this._tabNavigator.bind(this)();
return (
<Tabs/>
);
}
}
in _tabNavigator. this.props.navigation:
Object {
"actions": Object {
"closeDrawer": [Function closeDrawer],
"goBack": [Function goBack],
"navigate": [Function navigate],
"openDrawer": [Function openDrawer],
"setParams": [Function setParams],
"toggleDrawer": [Function toggleDrawer],
},
"addListener": [Function addListener],
"closeDrawer": [Function anonymous],
"dangerouslyGetParent": [Function anonymous],
"dispatch": [Function anonymous],
"getChildNavigation": [Function getChildNavigation],
"getParam": [Function anonymous],
"getScreenProps": [Function anonymous],
"goBack": [Function anonymous],
"isFocused": [Function isFocused],
"navigate": [Function anonymous],
"openDrawer": [Function anonymous],
"router": undefined,
"setParams": [Function anonymous],
"state": Object {
"key": "Main",
"params": undefined,
"routeName": "Main",
},
"toggleDrawer": [Function anonymous],
}
(我希望所有道具(例如openDrawer)都与DynamicTabNavigator相同,而且我不明白为什么它们不是这样)
in Profile. this.props:
Object {
"appMode": "WORK_MODE",
"dispatch": [Function anonymous],
"navigation": Object {
"actions": Object {
"dismiss": [Function dismiss],
"goBack": [Function goBack],
"navigate": [Function navigate],
"pop": [Function pop],
"popToTop": [Function popToTop],
"push": [Function push],
"replace": [Function replace],
"reset": [Function reset],
"setParams": [Function setParams],
},
"addListener": [Function addListener],
"dangerouslyGetParent": [Function anonymous],
"dismiss": [Function anonymous],
"dispatch": [Function anonymous],
"getChildNavigation": [Function getChildNavigation],
"getParam": [Function anonymous],
"getScreenProps": [Function anonymous],
"goBack": [Function anonymous],
"isFocused": [Function isFocused],
"navigate": [Function anonymous],
"pop": [Function anonymous],
"popToTop": [Function anonymous],
"push": [Function anonymous],
"replace": [Function anonymous],
"reset": [Function anonymous],
"router": undefined,
"setParams": [Function anonymous],
"state": Object {
"key": "id-1547113035295-8",
"routeName": "Profile",
},
},
"screenProps": undefined,
}
我不确定如何实施您的解决方案...
TabRoutes
中有您在示例中指定的三个屏幕这是我根据您的示例编写的代码。但是,我不确定CustomTabBar
中包含哪个组件。你能详细说明吗?
import React from 'react';
class CustomTabBar extends React.Component {
render() {
// a tab bar component has a routes object in the navigation state
const { navigation } = this.props;
// appState is extracted from redux state, see below
if (this.props.appState) {
return (
<View>
<???
name='First'
onPress={this.navigationHandler}
focused={navigation.state.index === index}
/>
<???
name='Second'
onPress={this.navigationHandler}
focused={navigation.state.index === index}
/>
</View>
);
} else {
return (
<View>
<???
name='First'
onPress={this.navigationHandler}
focused={navigation.state.index === index}
/>
<???
name='Third'
onPress={this.navigationHandler}
focused={navigation.state.index === index}
/>
</View>
);
}
}
navigationHandler = (name) => {
const {navigation} = this.props;
navigation.navigate(name);
}
}
const mapStateToProps = state => {
const { appState } = state.app;
return { appState };
};
export default connect(mapStateToProps)(CustomTabBar);
答案 0 :(得分:3)
您还可以保持TabNavigator不变,并使用自定义TabBarItem组件创建一个自定义TabBar组件。您可以将该自定义TabBar连接到您的redux状态,并根据需要隐藏/显示自定义TabBarItems。
然后像往常一样简单地将所有可能的路由添加到TabNavigator。
路线
const TabRoutes = createBottomTabNavigator({
First: {screen: SomeScreen},
Second: {screen: SomeStack},
Third: {screen: AnotherStack}
},{
initialRouteName: 'First',
tabBarComponent: CustomTabBar
});
CustomTabBar
关于如何隐藏选项卡栏项目的一些基本示例,因此显然需要根据自己的要求进行调整
import CustomTabBarItem from '...' ;
class CustomTabBar extends React.Component {
render() {
// a tab bar component has a routes object in the navigation state
const {navigation, appState} = this.props;
const routes = navigation.state.routes;
return (
<View style={styles.container}>
// You map over all existing routes defined in TabNavigator
{routes.map((route, index) => {
// This could be improved, but it's just to show a possible solution
if (appState && route.routeName === 'x') {
return <View/>;
} else if (!appState && route.routeName === 'y') {
return <View/>;
}
return (<CustomTabBarIcon
key={route.key}
name={route.routeName}
onPress={this.navigationHandler}
focused={navigation.state.index === index}
appState={appState}
/>);
})}
</View>
);
}
navigationHandler = (name) => {
const {navigation} = this.props;
navigation.navigate(name);
}
}
const styles = StyleSheet.create({
container: {
width: '100%',
flexDirection: 'row'
}
})
const mapStateToProps = (state) => {
return {
appState: state.app.appState // boolean
};
};
export default connect(mapStateToProps)(CustomTabBar);
CustomTabBarItem
class CustomTabBarItem extends React.PureComponent {
render() {
const {name, focused} = this.props;
return (
<View style={styles.tabItem}>
// Some icon maybe
<Text style={/*different style for focused / unfocused tab*/}>{name}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
tabItem: {
flex: 1
}
})
答案 1 :(得分:1)
好吧,看完代码后,我看到了问题所在……问题是..您没有以正确的方式嵌套导航道具。当您在抽屉式导航器中嵌套一个普通的选项卡导航器时,它可以很好地工作,因为您没有渲染任何东西,所以您正在做它的反应导航方式。
但是..当您尝试使用动态选项卡导航器时,没有将选项卡导航器返回到抽屉式导航器,而是返回了组件
export function tabNavigator(){
let tabs = {};
const a = 2;
if (a > 1) { // the actual line is obviously different, I am trying to simplify the example
tabs = { RequestStack, ManageStack, MessagesStack, ProfileStack };
} else {
tabs = { WorkStack, ManageStack, MessagesStack, ProfileStack };
}
// console.log('in _tabNavigator. this.props.navigation:');
//console.log(navigation);
return createBottomTabNavigator(tabs, {
headerMode: 'none',
});
}
,在他的渲染功能中,您有一个导航器...
所以..您有2种可能的解决方案...
第一个只是使用一个函数并在没有自定义组件的情况下调用它
import {tabNavigator} from './TabNavigator'
const Tabs = tabNavigator()
export default createDrawerNavigator({
Drawer: MainDrawerNavigator,
Main: Tabs
}, {
contentComponent: props => <Drawer {...props} />,
});
并在您的根导航器中
_tabNavigator() {
let tabs = {};
const a = 2;
if (a > 1) { // the actual line is obviously different, I am trying to simplify the example
tabs = { RequestStack: {screen:<RequestStack navigation={this.props.navigation}/>, navigationOptions: () => ({
tabBarLabel:'Request',
tabBarIcon:<YourComponent/>})},
ManageStack:{screen:<ManageStack navigation={this.props.navigation}/>}, MessagesStack:{screen:<MessagesStack navigation={this.props.navigation}/>},
ProfileStack:{screen:<ProfileStack navigation={this.props.navigation}/>}};
} else {
tabs = { WorkStack, ManageStack, MessagesStack, ProfileStack }; //repeat
}
console.log('in _tabNavigator. this.props.navigation:');
console.log(this.props.navigation);
return createBottomTabNavigator(tabs, {
headerMode: 'none',
});
不知道这是否行得通
第二个解决方案
手动将导航道具传递给dynamyc Tabnavigator的所有屏幕,这确实很丑陋,但是当您将导航器放入组件内部时,这是一种解决方法
const ProfileStack = ({props}) => createStackNavigator({
Profile: {
screen: <Profile navigation={props.navigation}/>,
navigationOptions: () => ({
title: 'Profile'
})
}
}, {
initialRouteName: 'Profile'
});
提示:请勿在组件内部进行动态导航,如果不手动传递导航道具,则会丢失
编辑N2:
{amount: "x", xParty: "x", yAction: "x", zParty: "x", objectKey: "-ggj34h3j4h3hj4hj3")