Реагирующая навигация предотвращает сбой приложения в сборке релиза
У меня действительно странное поведение в моем реактивном приложении. Я отследил это до минимального примера.
У меня есть SwitchNavigator с двумя компонентами. Первый компонент ничего не делает, кроме перехода ко второму компоненту после 2000 мс. Второй компонент имеет ошибку в методе рендеринга (например, он пытается рендерить некоторые неопределенные вещи "test.error").
Компонент кода 2:
render = () => {
return (
<View>
{
test.error
}
</View>
)
}
Во время разработки я получаю обычный "красный экран смерти", который говорит мне: "ReferenceError: ReferenceError: test is notfined". Это ожидаемое поведение. Но при сборке релиза приложение завершается сбоем молча и просто отображает пустой экран. Нет сбоя приложения.
Дополнительная информация: то же самое приложение вызывает сбой в сборке релиза (как и ожидалось), когда часть ошибки отображается после того, как компонент был монтирован.
Компонент 2 - вылетает, как и ожидалось:
class Test extends Component {
state = {
error: false
};
componentDidMount = () => {
setTimeout(() => {
this.setState({error: true});
}, 0)
};
render = () => {
if (this.state.error) {
return (
<View>
{
test.error
}
</View>
)
} else {
return (
<View>
Test
</View>
)
}
}
}
Дополнительная информация:
- когда я использую Компонент 2 в качестве первоначально названного Компонента, мое приложение действительно падает, как ожидалось. Кажется, только чтобы не вылететь после навигации.
- Поведение то же самое с StackNavigator
Версии:
- Реагировать: 16.3.1
- ReactNative: 55,4
- ReactNavigation: пробовал с 1.6.0 и 2.18.2
- Bugsnag: 2.12.4
1 ответ
Для тех, у кого такая же проблема. Это не имело ничего общего с ошибками или реакцией навигации.
Проблема заключалась в том, что ошибки в методе рендеринга не приводили к аварийному завершению работы приложения в режиме выпуска. Я думаю, что причина кроется в React 16 и функции ErrorBoundary.
Решением в моем случае было добавить ErrorBoundary в мой App.js (см. https://reactjs.org/docs/error-boundaries.html). Здесь я теперь могу обработать ошибку и сообщить об этом в Bugsnag.
componentDidCatch = (e, message) => {
bugsnag.notify(e);
Alert.alert(
I18n.t('GLOBAL__FATAL_ERROR'),
I18n.t('GLOBAL__FATAL_ERROR_MESSAGE'),
[
{
text: I18n.t('GLOBAL__FATAL_ERROR_RESTART'),
onPress: () => BackHandler.exitApp()
}
]
);
};