Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native app does not crash as expected

We have been investigating issues in our app where we just see a white screen and no crash is logged. Goes for both Android and iOS

The issue seem to be related to the use of async/await or promises.

We have found that we can reproduce the white screen issue locally when using async/await or promises.

The issue can be reproduced with the following code (tried to simplify it as much as possible). Replace App.js in a new project with the following:

import React, {Fragment} from 'react';
import {Text} from 'react-native';

class App extends React.Component {
  state = {isMounted: false};

  async componentDidMount() {
    await Promise.resolve(1);
    this.setState({isMounted: true});
  }

  render() {
    if (this.state.isMounted) {
      this.state.isMounted.test();
    }
    return (
      <Fragment>
        <Text>test</Text>
      </Fragment>
    );
  }
}

export default App;

I also pushed a test project on github

I would expect the app to crash as isMounted does not contains a test method.

When running locally I get the red box stating that an error occurred as expected

TypeError: this.state.isMounted.test is not a function. (In 'this.state.isMounted.test()', 'this.state.isMounted.test' is undefined)

This error is located at:
    in App (at renderApplication.js:40)
    in RCTView (at View.js:35)
    in View (at AppContainer.js:98)
    in RCTView (at View.js:35)
    in View (at AppContainer.js:115)
    in AppContainer (at renderApplication.js:39)

...

but when running a release build the app does not crash and no error is reported. This makes it very hard for us to find and fix issues like this as we are totally blind.

If I comment out

await Promise.resolve(1);

It crash as expected in a release build

React Native version: 0.60.5

Are we wrong in assuming that the above code should result in an app crash?

like image 900
René Madsen Avatar asked Nov 06 '22 14:11

René Madsen


1 Answers

Found that error-boundaries was the missing piece. Implementing an error boundary on the root level allows us to manually log these errors to our crash handling system.

As a side note I can also mention that if you use redux-saga and you throw an error, the error by default seem to be swallowed. So if you want to handle these uncaught errors you can implement the onError option in createSagaMiddleware

like image 59
René Madsen Avatar answered Nov 15 '22 13:11

René Madsen