aksonov / react-native-router-flux

The first declarative React Native router
MIT License
8.98k stars 2.11k forks source link

Dynamic control tabbar display and hide #2349

Closed as123456py closed 7 years ago

as123456py commented 7 years ago

Version

Expected behaviour

I expected that I can dynamic control tabbar display and hide. For example , there are two roles for user in my system. Different roles have different permissions,one of them has four Scenes on tabbar,and the other has five.When I log in with different roles, display the corresponding Scenes on tabbar. At first,I use State to control Scenes display and hide,like this: `

          <Scene key="root" panHandlers={null}>
            <Scene key="Login" component={Login} title="login"  hideNavBar={true}  />
            <Scene key='upPortal' lazy={true} tabs={true} hideNavBar={true}  >
                   <Scene key='index' title='index' hideNavBar={true} >
                        //other scene
                   </Scene>
                   <Scene key='project'  title='project'  hideNavBar={true} >
                       //other scene
                   </Scene>
                   {
                     this.state.flag?
                     <Scene key='business'   title='business' hideNavBar={true} >
                            //other scene
                     </Scene>:null
                   }
                   <Scene key='custom' title='custom'  hideNavBar={true} >
                           //other scene
                   </Scene>
                   <Scene key="myhome" title="myhome" hideNavBar={true} >
                       //other scene
                    </Scene>
           </Scene>
       </Scene>`

but it is not work. Then I think that I can render the whole Router again when the user log in with different role ,but it is still not work.

I need help ,Is there a good solution to dynamic control one of the tabbar display and hide?

pgonzalez-santiago commented 7 years ago

Hi, in my APP I want to show or hide the tabbar depending if the user is logged or not. I have this information in the store so the only thing that I have to do is check if the token exists.

This is what I have,

               <Tabs  key="listTabs"
                      swipeEnabled={true}
                      showLabel={true}
                      lazy={true}
                      tabBarPosition="top"
                      hideTabBar={this.props.token === null}
                >
                .....
                </Tabs>
as123456py commented 7 years ago

@pgonzalez-santiago Hi,I want to show or hide one of tabbar's children.When hideTabBar is true ,there will hide all of them.

as123456py commented 7 years ago

Can anyone help me ?

aksonov commented 7 years ago

It is not supported, sorry.

thebergamo commented 7 years ago

@aksonov but it's supported by v4? Or will be? Can you share some information about how to implement this kind of thing in v4? Or directions to open a PR for it?

tasharofi commented 6 years ago

@aksonov is this feature still not supported? it would be a huge help if we can do a conditional scene rendering...

as123456py commented 6 years ago

@tasharofi @thebergamo there is one solution for me which can help you. 1、Create a separate componet that contains your tabbars 2、In this componet,deal with your business 3、Import this componet in your business componet

this is my CustomTabBar


const defaultIcon = [require('../../images/Index.png'),
               require('../../images/Business.png'),
               require('../../images/Tourists.png'),
               require('../../images/My.png')];

 const activeInco = [require('../../images/ActiveIndex.png'),
                require('../../images/ActiveBusiness.png'),
                require('../../images/ActiveTourists.png'),
                require('../../images/ActiveMy.png')];
const titleInfo = ['首页','业务','客源','我的'];

const styles = StyleSheet.create({

    tabView:{
      position:"absolute",
      backgroundColor:"#fff",
      bottom:0,
      left:0,
      width:Dimensions.get('window').width,
      flexDirection:"row",
      paddingTop:10,
      borderTopWidth:1,
      borderColor:"#ececec"
    },
    marginTop10:{
      marginTop:5,
      marginBottom:5,
    },
    redIcon:{
      width:10,
      height:10,
      backgroundColor:'red',
      position:'absolute',
      right:25,
      top:5,
      borderRadius:5,
    },
})

const sonViewStyle4 = StyleSheet.create({
    sonView:{
      alignItems:"center",
      justifyContent:"center",
      width:(Dimensions.get('window').width)/3
    }
})
const sonViewStyle5 = StyleSheet.create({
    sonView:{
      alignItems:"center",
      justifyContent:"center",
      width:(Dimensions.get('window').width)/4
    }
})

export default class CustomTabBar extends Component {
  constructor(props){
    super(props);
    this.state={
      active:this.props.focused,
      barIndex:this.props.barIndex,
      isProject:false,
      checkIndex:this.props.checkIndex,
      user:{},
      sonViewStyle:sonViewStyle4,
      redFlag:false,
    };
  }

  componentDidMount(){
    this.loadCurrentUser()
  }

  componentWillReceiveProps(nextprops){
    if(nextprops && nextprops.isNeedRefresh == 1){
      this.loadCurrentUser()
    }
  }

  loadCurrentUser(){
    storage.load({
      key:keys.currentUser
    }).then(user=>{
      if (user) {
        if (user.projectManager) { //Different roles have different permissions
          this.setState({user:user,isProject:true,sonViewStyle:sonViewStyle5});
        }else {
          this.setState({user:user,isProject:false,sonViewStyle:sonViewStyle4});
        }
      }else {
        this.setState({user:null,isProject:false,sonViewStyle:sonViewStyle4});
      }
    }).catch(error=>{
      this.setState({user:null,isProject:false,sonViewStyle:sonViewStyle4});
    })
  }

  renderTab(item,index){
    if (!this.state.sonViewStyle) {
      return null;
    }
    if (!this.state.isProject&&index===1) {
      return null;
    }
    if (this.state.checkIndex === index) {
      return <TouchableHighlight key={index} underlayColor="transparent">
            <View style={this.state.sonViewStyle.sonView}>
                  <Image  source={activeInco[index]}/>
                  <Text style={[fonts.tinyText_Blue,styles.marginTop10]}>{titleInfo[index]}</Text>
            </View>
      </TouchableHighlight>
    }else {
      return <TouchableHighlight key={index} underlayColor="transparent" onPress={()=>{this.checkPress(index)}}>
            <View style={this.state.sonViewStyle.sonView}>
                  <Image  source={defaultIcon[index]}/>
                  <Text style={[fonts.tinyText_Gray,styles.marginTop10]}>{titleInfo[index]}</Text>
            </View>
      </TouchableHighlight>
    }
  }
  checkPress(checkIndex){
    switch (checkIndex) {
      case 0:
        Actions.reset('Index',{});
        break;
      case 1:
        Actions.reset('MyProject',{});
        break;
      case 2:
        Actions.reset('TouristIndex',{});
        break;
      case 3:
        Actions.reset('PersonalIndex',{});
        break;
      default:
        Actions.reset('Index',{});
    }
  }
  render() {
    return (
      <View style={styles.tabView}>
            {
              activeInco.map((item,key)=>{
                return this.renderTab(item,key)
              })
            }
      </View>
    );
  }
}

and then import CustomTabBar in the business Componet


import CustomTabBar from '../../commonComponents/tabBar/CustomTabBar';

...

render() {
    return (
    <CustomTabBar checkIndex={0} />
 )
}

There is a problem that can't be solved.When press tab icon ,business component will refresh everytime.it can not cache data.

Hope to be useful to you

lelup commented 6 years ago

you can duplicate and control tabbar when you click button loggin:

       <Scene key='upPortal' lazy={true} tabs={true} hideNavBar={true}  >
               <Scene key='index' title='index' hideNavBar={true} >
                    //other scene
               </Scene>
               <Scene key='project'  title='project'  hideNavBar={true} >
                   //other scene
               </Scene>
                 <Scene key='business'   title='business' hideNavBar={true} >
                        //other scene
                 </Scene>
               <Scene key='custom' title='custom'  hideNavBar={true} >
                       //other scene
               </Scene>
               <Scene key="myhome" title="myhome" hideNavBar={true} >
                   //other scene
                </Scene>
       </Scene>

        <Scene key='upPortal2' lazy={true} tabs={true} hideNavBar={true}  >
               <Scene key='index' title='index' hideNavBar={true} >
                    //other scene
               </Scene>
               <Scene key='project'  title='project'  hideNavBar={true} >
                   //other scene
               </Scene>
               <Scene key='custom' title='custom'  hideNavBar={true} >
                       //other scene
               </Scene>
               <Scene key="myhome" title="myhome" hideNavBar={true} >
                   //other scene
                </Scene>
       </Scene>

.... _checkTabbar() { if (condition) { Action.upPortal(); } Action.upPortal2(); }

eugrdn commented 6 years ago

Another variant is to use tabBarComponent prop, that will render links for needed scenes dynamically.

a-fortunato commented 5 years ago

If anyone ends up here and still struggles with this, I've found a pretty good answer myself using tabBarComponent as explained in the next example: https://stackoverflow.com/questions/54872145/programatically-hiding-and-showing-individual-tabs-in-react-native-router-flux-t.