Search code examples
androidreact-nativereact-navigationtabnavigator

How to setParams in `Screen` when use `TabNavigator`(ES6)?


(Android React-Native 0.47)

How could i do to give the two PopularTab diff params and get this params in PopularTab, I've try many times ,but failed. the only params i can get is navigation.key and navigation.routeName:

const Popular = TabNavigator({
  IOS: {
     screen: PopularTab,
     //I try to code here to set the params but fail.
     //eg:  data: 'param1'
      },
  Android: {
    screen: PopularTab,
      },
   },
{
   tabBarPosition: 'bottom',
   tabBarOptions: {
   activeTintColor: '#e91e63',
    }
  }
 );

Solution

  • There are three ways to achieve this, see which suits your need.

    1. Suggest to do this official way, via screenProps

    screenProps seems also suit your needs, with unidirectional design pattern.

    helper function

    function ScreenWithDefaultParams(Comp, defaultParams) {
        return class extends Component {
            render() {
                return (<Comp {...this.props} screenProps={defaultParams} />)
            }
        }
    }
    

    TabNavigation definition

    IOS: {
        screen: ScreenWithDefaultParams(PopularTab, {test: 'default'})
    },
    

    And then you can get it inside PopularTab:

    class PopularTab extends Component {
        render() {
            /* get default screenProps */
            console.log('default screenProps here!', this.props.screenProps);
        }
    }
    

    2. Workaround for set default navigation params

    Although it works, there's some problem with it. Firstly, as you see you got warning about Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, that is because every time you call setParams, navigationOptions will be trigger again so react-native warn you that might be an anti-pattern, or might cause an infinite loop.

    Although we know it won't be an infinite loop, the warning won't disappear because react-native compiler never satisfied with it.

    helper function

    function setDefaultParams(nav, defaultParams) {
        const { state, setParams } = nav.navigation;
        const params = state.params || {};
    
        let token = btoa(JSON.stringify(defaultParams));
        if (params[token]) return;
    
        setParams({ [token]: true, ...defaultParams });
    }
    

    TabNavigation definition

    IOS: {
        screen: PopularTab,
        navigationOptions: (nav) => {
            setDefaultParams(nav, {test: 'default'});
        }
    },
    

    And then you can get it inside PopularTab:

    class PopularTab extends Component {
        render() {
            const { state, setParams, navigate } = this.props.navigation;
            const params = state.params || {};
    
            /* get default set params */
            console.log('default param here!', params.test);
        }
    }
    

    3. set component props in navigators

    If you want to make it happens with normal Component props:

    TabNavigation definition

    IOS: {
        screen: (props) => <PopularTab {...props} test='default' />,
    },
    

    And then you can get it inside PopularTab:

    class PopularTab extends Component {
        render() {
            /* get default props */
            console.log('default props here!', this.props.test);
        }
    }