移除 android 反应本机 webview 上的默认错误页面
Remove android default error page on react native webview
我在 React Native 中使用 webview,我想在发生某些错误时显示自定义错误消息(例如,没有互联网连接)。
我的代码:
<WebView
renderError={() => (
<MissingConnection />
)}
other params....
/>
当加载网页出错时,webview 会在几分之一秒内显示默认的 android 错误,例如:
然后我的 MissingConnection
组件弹出,隐藏了 webview。
有没有办法完全删除默认的 android 错误屏幕?只闪了几分之一秒,结果感觉真的不对。
首先:你做得对。
我最近观察到同样的问题并做了一些调查。问题不在于您的代码或 React Native 或 react-native-webview
.
这只是 Android 的 WebView
的默认行为。很多Java开发者遇到同样的问题,SO上相关线程的例子:
webview error while loading a page without internet
Prevent WebView from displaying "web page not available"
Android WebView onReceivedError()
通常的解决方法是:
在尝试加载任何内容之前检查互联网连接(防止失败)
快速删除错误内容并在onReceivedError
中显示您自己的内容(基本上映射到react-native-webview
中的renderError
方法)。有时加载本地 url 就像在 Java here.
中所做的那样
注意有一个覆盖层,如果完全没有错误就将其删除。 react-native-webview
反其道而行之,出现错误时显示叠加层。但是 Activity 指示器叠加层是一个很好的例子,它会一直显示直到加载完成或遇到错误。
据我所知,除了这些令人失望的方式,我们无能为力,因为我不想与系统作斗争。
编辑:Android 的 Firefox Focus 在错误处理程序中快速替换内容。
这是在 Java 中完成的,来源如下:
和
所以我想我们是好伙伴!
编辑 2:我很好奇在真正的 Android 设备上不处于调试模式时这是否真的可见。我有根据的猜测是代码执行得更快而且根本不应该是可见的。顺便说一句,此页面可能仅针对 404(未找到)错误显示,如果您使用硬编码 urls 和您自己的服务器,则这种情况不太可能发生。
编辑 3:本机错误页面 在发布模式下在真实设备上可见运行。防止这种闪烁的唯一方法是创建一个覆盖层。我在 https://github.com/react-native-community/react-native-webview/issues/474#issuecomment-487022106.
处打开了一个与另一个错误相关的问题,该错误也用 react-native-webview
解决了这个问题
我的解决方案是警报功能
import React, { Component } from 'react';
import { Alert } from 'react-native';
import { View, Spinner } from 'native-base';
import { WebView } from 'react-native-webview';
export default class ExampleScreen extends Component {
displaySpinner() {
return (
<View style={{ flex: 1 }}>
<Spinner color="blue" />
</View>
);
}
displayError() {
Alert.alert(
"no_internet",
"require_internet_connection",
[
{ text: 'OK', onPress: () => this.props.navigation.goBack() },
],
{ cancelable: false });
}
render() {
return (
<WebView onError={() => this.displayError()}
startInLoadingState={true}
renderLoading={() => {
return this.displaySpinner();
}}
source={{ uri: 'https://example.com' }} />
);
}
};
实际上,就我而言,这个解决方案很管用
import React, { useEffect, useRef } from 'react';
import { StyleSheet, View, BackHandler } from 'react-native';
import { colors, variables } from 'utils/theme';
import { WebView } from 'react-native-webview';
import { Button, Spinner, Text } from 'components';
import { fa } from 'utils/constants/locales';
const uri = YOUR_WEB_PAGE_URL
const Loading = () => {
return (
<View style={styles.loadingWrapper}>
<Spinner />
<Text style={styles.loading}>{fa.proEducation.loading}</Text>
</View>
);
};
const Error = ({ reload }) => {
return (
<View style={styles.loadingWrapper}>
<Button
style={styles.retry}
label={fa.proEducation.retry}
primary
onPress={reload}
/>
</View>
);
};
const ProEducation = () => {
const webview = useRef(null);
const canGoBackRef = useRef(false);
const onAndroidBackPress = () => {
if (canGoBackRef.current && webview.current) {
webview.current.goBack();
return true;
}
return false;
};
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', onAndroidBackPress);
return () => {
BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress);
};
}, []);
const onNavigationStateChange = ({ canGoBack }) => {
canGoBackRef.current = canGoBack;
};
const reload = () => webview.current.reload();
return (
<View style={styles.wrapper}>
<WebView
ref={webview}
source={{ uri }}
style={styles.webView}
onNavigationStateChange={onNavigationStateChange}
javaScriptEnabled
domStorageEnabled
renderLoading={() => <Loading />}
renderError={() => <Error reload={reload} />}
startInLoadingState
/>
</View>
);
};
const styles = StyleSheet.create({
loading: {
color: colors.lightBlack,
fontSize: 15,
marginTop: 8,
textAlign: 'center',
},
loadingWrapper: {
backgroundColor: colors.white,
bottom: 0,
flex: 1,
justifyContent: 'center',
left: 0,
marginBottom: 'auto',
marginLeft: 'auto',
marginRight: 'auto',
marginTop: 'auto',
position: 'absolute',
right: 0,
top: 0,
},
retry: {
alignSelf: 'center',
paddingHorizontal: variables.gutter,
paddingVertical: variables.gutter / 2,
},
webView: {
flex: 1,
},
wrapper: {
backgroundColor: colors.bg,
flex: 1,
},
});
export default ProEducation;
我在 React Native 中使用 webview,我想在发生某些错误时显示自定义错误消息(例如,没有互联网连接)。
我的代码:
<WebView
renderError={() => (
<MissingConnection />
)}
other params....
/>
当加载网页出错时,webview 会在几分之一秒内显示默认的 android 错误,例如:
MissingConnection
组件弹出,隐藏了 webview。
有没有办法完全删除默认的 android 错误屏幕?只闪了几分之一秒,结果感觉真的不对。
首先:你做得对。
我最近观察到同样的问题并做了一些调查。问题不在于您的代码或 React Native 或 react-native-webview
.
这只是 Android 的 WebView
的默认行为。很多Java开发者遇到同样的问题,SO上相关线程的例子:
webview error while loading a page without internet
Prevent WebView from displaying "web page not available"
Android WebView onReceivedError()
通常的解决方法是:
在尝试加载任何内容之前检查互联网连接(防止失败)
快速删除错误内容并在
onReceivedError
中显示您自己的内容(基本上映射到react-native-webview
中的renderError
方法)。有时加载本地 url 就像在 Java here. 中所做的那样
注意有一个覆盖层,如果完全没有错误就将其删除。
react-native-webview
反其道而行之,出现错误时显示叠加层。但是 Activity 指示器叠加层是一个很好的例子,它会一直显示直到加载完成或遇到错误。
据我所知,除了这些令人失望的方式,我们无能为力,因为我不想与系统作斗争。
编辑:Android 的 Firefox Focus 在错误处理程序中快速替换内容。
这是在 Java 中完成的,来源如下:
和
所以我想我们是好伙伴!
编辑 2:我很好奇在真正的 Android 设备上不处于调试模式时这是否真的可见。我有根据的猜测是代码执行得更快而且根本不应该是可见的。顺便说一句,此页面可能仅针对 404(未找到)错误显示,如果您使用硬编码 urls 和您自己的服务器,则这种情况不太可能发生。
编辑 3:本机错误页面 在发布模式下在真实设备上可见运行。防止这种闪烁的唯一方法是创建一个覆盖层。我在 https://github.com/react-native-community/react-native-webview/issues/474#issuecomment-487022106.
处打开了一个与另一个错误相关的问题,该错误也用react-native-webview
解决了这个问题
我的解决方案是警报功能
import React, { Component } from 'react';
import { Alert } from 'react-native';
import { View, Spinner } from 'native-base';
import { WebView } from 'react-native-webview';
export default class ExampleScreen extends Component {
displaySpinner() {
return (
<View style={{ flex: 1 }}>
<Spinner color="blue" />
</View>
);
}
displayError() {
Alert.alert(
"no_internet",
"require_internet_connection",
[
{ text: 'OK', onPress: () => this.props.navigation.goBack() },
],
{ cancelable: false });
}
render() {
return (
<WebView onError={() => this.displayError()}
startInLoadingState={true}
renderLoading={() => {
return this.displaySpinner();
}}
source={{ uri: 'https://example.com' }} />
);
}
};
实际上,就我而言,这个解决方案很管用
import React, { useEffect, useRef } from 'react';
import { StyleSheet, View, BackHandler } from 'react-native';
import { colors, variables } from 'utils/theme';
import { WebView } from 'react-native-webview';
import { Button, Spinner, Text } from 'components';
import { fa } from 'utils/constants/locales';
const uri = YOUR_WEB_PAGE_URL
const Loading = () => {
return (
<View style={styles.loadingWrapper}>
<Spinner />
<Text style={styles.loading}>{fa.proEducation.loading}</Text>
</View>
);
};
const Error = ({ reload }) => {
return (
<View style={styles.loadingWrapper}>
<Button
style={styles.retry}
label={fa.proEducation.retry}
primary
onPress={reload}
/>
</View>
);
};
const ProEducation = () => {
const webview = useRef(null);
const canGoBackRef = useRef(false);
const onAndroidBackPress = () => {
if (canGoBackRef.current && webview.current) {
webview.current.goBack();
return true;
}
return false;
};
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', onAndroidBackPress);
return () => {
BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress);
};
}, []);
const onNavigationStateChange = ({ canGoBack }) => {
canGoBackRef.current = canGoBack;
};
const reload = () => webview.current.reload();
return (
<View style={styles.wrapper}>
<WebView
ref={webview}
source={{ uri }}
style={styles.webView}
onNavigationStateChange={onNavigationStateChange}
javaScriptEnabled
domStorageEnabled
renderLoading={() => <Loading />}
renderError={() => <Error reload={reload} />}
startInLoadingState
/>
</View>
);
};
const styles = StyleSheet.create({
loading: {
color: colors.lightBlack,
fontSize: 15,
marginTop: 8,
textAlign: 'center',
},
loadingWrapper: {
backgroundColor: colors.white,
bottom: 0,
flex: 1,
justifyContent: 'center',
left: 0,
marginBottom: 'auto',
marginLeft: 'auto',
marginRight: 'auto',
marginTop: 'auto',
position: 'absolute',
right: 0,
top: 0,
},
retry: {
alignSelf: 'center',
paddingHorizontal: variables.gutter,
paddingVertical: variables.gutter / 2,
},
webView: {
flex: 1,
},
wrapper: {
backgroundColor: colors.bg,
flex: 1,
},
});
export default ProEducation;