Passing props to tabNavigator's screens

2019-08-17 05:59发布

问题:

In my app, I want to pass some data in my createMaterialTopTabNavigator (const NewTab) to both it's child screens (Graphical and Tabular). The data in child screens changes on the basis of the dropdown value in the custom header that will be above createMaterialTopTabNavigator. As soon as the value from the dropdown is selected, it will trigger a fetch request in both the Graphical and Tabular Screen.

Here is my App.js where I am routing all my screens.

const NewTab = createMaterialTopTabNavigator({
  Graphical: Graphical,
  Tabular: Tabular
});


const DailyStack = createStackNavigator({
  Dashboard,
  Daily,
  Login,
  SalesDashboard,
  About : {
    screen: NewTab, 

      navigationOptions : {
        header : <CustomHeader />
      }
  }
})


const MonthlyStack = createStackNavigator({
  Monthly: Monthly
})



const RangeStack = createStackNavigator({
  Range: Range
})



export const BottomTabNavigation = createBottomTabNavigator({
  Daily: {
    screen: DailyStack
  },
  Monthly: {
    screen: MonthlyStack
  },
  Range: {
    screen: RangeStack
  }
})



const DashboardStackNavigator = createStackNavigator({
  BottomTabNavigation:BottomTabNavigation,
}, {
  headerMode: 'none'
})


export const AppDrawerNavigator = createDrawerNavigator({
  DashboardStackNavigator,
  Login: {
    screen: Login
  },
  Logout: {
    screen: Logout
  }
})


const OpenNav = createSwitchNavigator({
  Splash: {screen: SplashScreen},
  Login: { screen: Login },
  Home: { screen: Home }

})


const AppNavigator = createStackNavigator({

  OpenNav,
  AppDrawerNavigator: { screen: AppDrawerNavigator },
  ClaimsDashboard: ClaimsDashboard
},{
  headerMode:'none'
});

class App extends Component {

  constructor(){
    super();

    console.disableYellowBox = true;
  }


  render() {
    return (
      <AppContainer />
    );
  }
};


const AppContainer = createAppContainer(AppNavigator);

export default App;

CustomHeader.js

import React, { Component } from 'react'
import { Text, View, Picker } from 'react-native'
import Icon from 'react-native-vector-icons/AntDesign'



    export default class CustomHeader extends Component {

      constructor(props) {
        super(props)

        this.state = {
          user: ''
        }
      }

      updateUser = (user) => {
        this.setState({ user: user })
     }


      render() {
       return (
          <View>
            <Icon name="arrowleft" size={30} onPress={navigation.goBack()} />

            <View>
            <Picker selectedValue = {this.state.user} onValueChange = {this.updateUser}>
                   <Picker.Item label = "Steve" value = "steve" />
                   <Picker.Item label = "Ellen" value = "ellen" />
                   <Picker.Item label = "Maria" value = "maria" />
                </Picker>
            </View>
          </View>
        )
      }
    }

Considering all files included in App.js, I tried using screenprops for the same, but is not sure how to do it.

In dire need for solution. Please help.

回答1:

Yes, you can use screenProps here as I made below, but I strongly recommend using third party to manage state like redux, mobx, etc... or simply using context.

class DailyStackWithData extends React.Component {
 static router = DailyStack.router

 state = {
  user: 'steve'
 }

 setUser = user => this.setState({ user })

 componentDidMount(){
  this.props.navigation.setParams({ setUser: this.setUser });
 }

 render(){
  const { user } = this.state;
  const { navigation } = this.props;
  return (<DailyStack screenProps={user} navigation={navigation}/>)
 }
}

export const BottomTabNavigation = createBottomTabNavigator({
 Daily: {
  screen: DailyStack
 },
 ...
});

CustomHeader.js

import React, { Component } from 'react';
import { Text, View, Picker } from 'react-native';
import Icon from 'react-native-vector-icons/AntDesign';
import { withNavigation } from "react-navigation";

class CustomHeader extends Component {

    constructor(props) {
        super(props)

        this.state = {
            user: ''
        }
    }

    updateUser = user => {
        const setUser = this.props.navigation.getParam('setUser', () => {});
        setUser(user);
        this.setState({ user: user });
    }


    render() {
        return (
            <View>
                <Icon name="arrowleft" size={30} onPress={()=>{}} />
                <View>
                    <Picker selectedValue = {this.state.user} onValueChange = {this.updateUser}>
                        <Picker.Item label = "Steve" value = "steve" />
                        <Picker.Item label = "Ellen" value = "ellen" />
                        <Picker.Item label = "Maria" value = "maria" />
                    </Picker>
                </View>
            </View>
        )
    }
}

export default withNavigation(CustomHeader)

and in Graphical or Tabular screen you can get that variable by screenProps props. I've made an example here