Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-navigation Error boundary that can navigate

What would be the cleanest way to wrap all screens managed by react-navigation in an error boundary that can also navigate. My current approach involves a top level component like:

class App extends Component{
  navigateTo(routeName) {
    this.navigator && this.navigator.dispatch(NavigationActions.navigate({ routeName }));
  }

  render(){
    return (
      <Provider store={store}>
        <PersistGate persistor={persistor}>
          <MenuProvider>
            <ErrorBoundary navigateTo={this.navigateTo.bind(this)}>
              <AppNavigator
                ref={navigator=> {
                  NavigationService.setTopLevelNavigator(navigator);
                  this.navigator = navigator;
                }}
              />
            </ErrorBoundary>
          </MenuProvider>
        </PersistGate>
      </Provider>
    )
  }
}

with a rather standard ErrorBoundary:

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);

    this.state = { error: null, info: null };
  }

  componentDidCatch(error, info) {
    this.setState({error, info});
    this.props.navigateTo('SomeScreen');
  }

  render() {
    if (this.state.error) {
      return (
        <Container>
          <Content>
            <Text> Got error: {JSON.stringify(this.state.error)}, info {JSON.stringify(this.state.info)} </Text>
          </Content>
        </Container>
      )
    }

    return this.props.children;
  }
}

However when an error occurs the navigator gets unmounted and ref is called again with null.

Alternatively, is there a way to have an ErrorBoundary as a descendant of AppNavigator that catches errors from any screen and can also access the navigator, eventually through a NavigationService?

like image 937
darfire Avatar asked Oct 11 '18 15:10

darfire


Video Answer


1 Answers

you should be able to do this with custom navigators, below is an example with the new react-navigation V3 createAppContainer api as per, https://reactnavigation.org/docs/en/custom-navigators.html.

We have just implemented a revision in our app to achieve this when upgrading to V3.

That way your AppNavigator will still be mounted when the error boundary hits and will have access to your navigation props.

const StackNavigator = createStackNavigator({..});

class AppNavigator extends React.Component {
 static router = StackNavigator.router;
  render() {
    const { navigation } = this.props;
    return (
      <ErrorBoundary navigation={navigation}>
        <StackNavigator navigation={navigation} />
      </ErrorBoundary>
    );
  }
}

const AppContainer = createAppContainer(AppNavigator);
export default AppContainer;
like image 104
Oliver Winter Avatar answered Oct 06 '22 00:10

Oliver Winter