Adam Katz
Adam Katz

Reputation: 6972

React-navigation tabnavigator reloads on parents state change

I am using the tabnavigator from react navigation. I have a parent component that looks like this

changeService(serviceName){
 this.setState({

 });
}

render() {
const { container } = styles
return (
<View style={container}>
  <Header
  clientName = {this.state.project}
  serviceName = {this.state.service}
  cancelClick = {this.handleExitClick}
  />
  <ServicesNavigator
  changeService = {this.changeService}
  />
</View>
);
}

Then my service navigator export looks like this

export default (props) => {
 const { screenProps, ...otherProps } = props;
 const ServicesNavigator = makeServiceNavigator(props);
 return <ServicesNavigator screenProps={{ ...screenProps, ...otherProps 
 }} />
};

The navigator itself looks like a normal navigator except it hsa navigationOptions equal to

tabBarOnPress: (scene, jumpToIndex) => {
    changeService(scene.scene.route.routeName)
    scene.jumpToIndex(scene.scene.index)
  },

Whenever i try to change tabs the navigator is reloading completely and going back to default tab selection. Is there no way to allow the tabnavigors parents state variables to change without reseting the tab navigator?

Upvotes: 0

Views: 1069

Answers (1)

blaz
blaz

Reputation: 4078

Whenever tabBarOnPress is triggered, it requests to update state of the parent component. Then due to React component lifecycle, state update will cause parent component to re-render, along with all its children. This is why your tab navigator is reseted all the times.

There are several solutions for your case:

1 - Use shouldComponentUpdate to guide when parent component to be updated. Since you want to retain ServicesNavigator whenever changeService is called, you want to avoid re-rendering on related state items.

shouldComponentUpdate(nextProps, nextState) {
    if (this.state.itemA !== nextState.itemA) {
        return false; // avoid re-rendering
    }
    return true;
}

This is dirty but working; however it will haunt you in the long run since it causes parent component's behaviours not idempotent.

Edit: I forgot you have the Header which reads the state. If you use shouldComponentUpdate in the parent component, then Header will not receive new props. So 1st option is not correct. Sorry about this.

2 - Don't let parent component hold the state anymore. In your sample code, parent component has state only because its children components need to communicate and share data with each others. So why don't you just keep the sharing data somewhere else? Best tools can be state management libraries like mobx or redux, which can be integrated quite easily with react-navigation

Upvotes: 1

Related Questions