I'm implementing my first react native project & it seems the best way to handle errors is with an app-level Error Boundary. I'm struggling to figure our how to integrate that with react-native-navigation. Current code looks like this:
# App.js
...
const startApp = () => {
Navigation.startSingleScreenApp({
screen: {
screen: 'App.Splash',
navigatorStyle: {
navBarHidden: true,
},
},
});
};
export function startTabs() {
registerScreens(store, Provider);
sagaMiddleware.run(RootSaga);
loadIcons().then(() => {
// Start app only if all icons are loaded
startApp();
});
}
startTabs();
And the screens.js:
# app/Screens.js
...
export default function registerScreens(store, Provider) {
Navigation.registerComponent('App.Splash', () => SplashContainer, store, Provider);
...
});
Because Navigation.startSingleScreenApp doesn't return a component, I'm struggling to figure out how to wrap an error boundary either immediately inside or outside the navigator. I tried scouring through react-native-navigation documentation, but couldn't find much help. Any ideas appreciated.
For the record, I solved this by wrapping the error boundary inside a parent provider, and passing that to each navigator screen. Eg:
// ProviderWithErrorBoundary.js
const ProviderWithErrorBoundary = ({ store, children }) => (
<Provider store={store}>
<ErrorBoundary>
{children}
</ErrorBoundary>
</Provider>
);
Then passed then into my Screens.js via
// Screens.js
export default function RegisterScreens(store, Provider) {
Navigation.registerComponent('App.Home', () => HomeContainer, store, Provider);
})
Hope this helps somebody
What I did when I had such requirement, I displayed Root HOC component, that wraps first screen, instead of actual first screen. Then you can handle errors inside Root, because it will be always loaded and use this.props.navigator of Root component to display errors, for example, with showModal().
Another benefit of having Root component that you can switch displayed root screen from side menu very easily naturally, without any special handling navigation actions. Or you can implement splash->login->home flow, like I did in the example below.
It can look like that:
class Root: Component {
static propTypes = {
navigator: PropTypes.instanceOf(Navigator).isRequired;
}
constructor(props) {
this.state = {
content: <Splash navigator={this.props.navigator} onLoadComplete={this.handleLoadComplete} />,
};
// Adding network interceptor with handleNetworkError() as callback
}
handleLoadComplete = () => {
this.setState({
content: <Login navigator={this.props.navigator} onLoginComplete={this.handleLoginComplete} />,
});
}
handleLoginComplete = () => {
this.setState({
content: <Home navigator={this.props.navigator} />,
});
}
handleNetworkError = (error) => {
this.props.navigator.showModal(screens.NetworkError, {
passProps: { error },
});
}
render() {
return this.content;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With