DickyT / react-native-tabbar-navigator

(aka React Native Tanner Navigator) A component which builds excellent Navigator + TabBar based application, have a good solution for implementing hidesBottomBarWhenPushed in iOS.
97 stars 29 forks source link

NavigationBar not refreshing #5

Closed rahuljiresal closed 8 years ago

rahuljiresal commented 8 years ago

So I've been trying to fix the bugs introduced by custom title components. Currently, the only bug I can see was that the NavigationBar doesn't refresh when you change the tabs. So the title stays once it is rendered. I tried fixing it, but it doesn't look to be straightforward. Especially with my limited expertise in React and React Native. Could you look into it?

DickyT commented 8 years ago

Hi, are you using the latest release which I post it tonight?

DickyT commented 8 years ago

I tried the latest demo code on master branch, it looks great, the state of the SegmentControl will be recored. issue5

I tried to update the sample code on rnplay later, I think there should be some configuration error on your code, could you show me?

rahuljiresal commented 8 years ago

I'm using the latest code from master. The title component is only getting rendered once, and when you change the tab back, it doesn't change. I'm also pasting the code, let me know if you need the styles too.

giphy

var style = StyleSheet.create({
  rootView: {
    flex: 1
  },
  tabContentStyle: {
    flex: 1,
    backgroundColor: 'ebebeb',
    justifyContent: 'center',
    alignItems: 'center'
  },
  textStyle: {
    color: '#333333',
    marginBottom: 25,
    fontSize: 17
  },
  navItem: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  arrowImage: {
    width: 200,
    height: 200,
    transform:[{rotate: '-45deg'}],
    backgroundColor: 'transparent',
    position: 'absolute',
    right: 0,
    top: 0
  }
});

class TabOne extends Component {
  constructor(props) {
    super(props);
    this.props.navComponent.setNavItems({
      title:{
        component: (
          <View
            style={styles.segmentControlContainer} >
            <SegmentedControlIOS
                style={ styles.segmentControl }
                values={['Pinned', 'All']}
                selectedIndex={1}
            />
          </View>
        )
      }
    });
  }
  render() {
    return (
      <View style={style.tabContentStyle}>
            <Text style={style.textStyle}>This is the content of Tab 1</Text>
            <Text style={style.textStyle}>Automatically marginTop = 64</Text>
            <Text style={style.textStyle}>TabBarNavigator.Item is the OnlyChild</Text>
            <Text style={style.textStyle}>You can wrap everything inside {'<View></View>'}</Text>
            <Text style={style.textStyle}>Slide to back is fully supported</Text>
      </View>   
    );
  }
}

class TabTwo extends Component {
  constructor(props) {
    super(props);
    this.props.navComponent.setNavItems({
      title:{
        component: (
          <Text style={{flex: 1, justifyContent: 'center', color: 'white', marginTop: 12, fontSize: 18}}>
              Title
            </Text>
        )
      }
    });
  }
  render() {
    return (
      <View style={style.tabContentStyle}>
        <Text style={style.textStyle}>This is the content of Tab 2</Text>
        <Text style={[style.textStyle, {marginBottom: 0}]}>A good implementation of</Text>
        <Text style={style.textStyle}>hidesBottomBarWhenPushed</Text>
        <Text style={style.textStyle}>Set as default by passing Props 'defaultTab'</Text>
        <TouchableOpacity onPress={ () => {}}>
          <Text style={[style.textStyle, {color: 'rgb(0,122,255)'}]}>Try to push a new page</Text>
        </TouchableOpacity>
        <Text style={style.textStyle}>And see the magic on the TabBar</Text>
      </View>
    );
  }
}

class TabBarNavigatorExample extends Component {
  render() {
    return (
      <TabBarNavigator
        navTintColor='ffffff'
        navBarTintColor='333333'
        tabTintColor='orange'
        tabBarTintColor='333333'
        onChange={(index)=>console.log(`selected index ${index}`)}>
        <TabBarNavigator.Item title='Tab 1' icon={{uri: base64Icon, scale: 3}}>
          <TabTwo />
        </TabBarNavigator.Item>
        <TabBarNavigator.Item title='Tab 2' defaultTab>
          <TabOne />
        </TabBarNavigator.Item>
      </TabBarNavigator>
    );
  }
}

var styles = StyleSheet.create({
    segmentControlContainer: {
        flex: 1,
        flexDirection: 'row',
        alignItems: 'center'
    },
    segmentControl: {
        width: 160
    }
});
DickyT commented 8 years ago

I am not sitting behind my computer now, I cannot run this code immediately. And the GIF seems is too short to re-produce this issue, can you record a longer gif?

PS. licecap on Mac seems like a excellent GIF recording tool.

rahuljiresal commented 8 years ago

Sorry, the GIF creation site clipped the video. I just updated my comment with a better GIF. Thanks.

DickyT commented 8 years ago

Oh I can see this now. This is a such normal issue while I am dealing with these kind of issue. The reason cause this problem is because the operation did not trigger the re-render. You can see the structure of the app, it is Navigator -> Tabbar, but the new pages will push directly on the Outer Navigator, while normal structure on native iOS is TabBar -> Navigators, and the new pages will push directly to their current Navigators. This way in RN is a good way to simulate the hidesBottomBarWhenPushed in native iOS.

Back to this issue, while you are clicking the TabBar, and RN will only re-render TabBar it self and the child elements of TabBar, so the Navigator is not re-rendered. You can see the reason why in I do not allow changing leftItem and rightItem in rootPage in the source code.

I already following the related issue on RN official issues, I think it will be little bit hard to solve this out in a short time, sorry

DickyT commented 8 years ago

@rahuljiresal But if you really need this feature, I can use some hack way to achieve this, I will try to fix this tomorrow. It is Remembrance holiday LOL

rahuljiresal commented 8 years ago

That would be really appreciated, thanks! I have spent quite a lot of time and energy on this. I can think of one way to do this. The Navigator sends a callback to the TabBarIOS, in which, we do setState on something that makes the Navigator re-render. Is that the hack way you were thinking of?

DickyT commented 8 years ago

The callback I think could not trigger the re-render, I was thinking sending the whole Navigator into the TabBar, and see if works. If it won`t work, the last & hack way is using a global event controller to force re-render.

rahuljiresal commented 8 years ago

I'd be really interested in seeing this hack. I'm only 3 weeks old in the Javascript (and RN) world. Still struggling my way through it lol

DickyT commented 8 years ago

RN seems attractive when you are enjoying the convenient feature on it, but if you got into some troubles, it will waste you lots of time to deal with it. I have been posting 2+ packages on it, and make the wrong things work. RN is still too young lol. But anyway, writing CSS is better than the AutoLayout in Xcode.

DickyT commented 8 years ago

@rahuljiresal I just fixed it without any hack! I just made everything logically and I did it! enjoy! I will update the README in several minutes

DickyT commented 8 years ago

@rahuljiresal The documentation and npm package is up-to-date.

rahuljiresal commented 8 years ago

@DickyT thanks again for fixing it. There was a bug in the navigation bar refreshing. I fixed it and submitted a pull request. Take a look at it.