我在React Native中使用的是Webview,并且想要在发生某些错误(例如,没有互联网连接)时显示自定义错误消息。
我的代码:
<WebView
renderError={() => (
<MissingConnection />
)}
other params....
/>
加载网页时出错,一秒钟之内,Webview就会显示默认的android错误,例如:
然后我的MissingConnection
组件会弹出,隐藏Web视图。
有没有办法完全删除默认的android错误屏幕?它只闪烁一秒钟,结果感觉确实不对。
答案 0 :(得分:1)
首先:您做对了。
我最近发现了同样的问题,并做了一些调查。问题不在于您的代码,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()
通常可以解决的建议是:
在尝试加载任何内容之前检查Internet连接(防止失败)
快速删除错误内容,并在onReceivedError
中显示您自己的内容(该内容基本上映射到renderError
中的react-native-webview
方法)。有时会像Java here一样加载本地URL。
请确保有一个覆盖层,以防万一没有错误。 react-native-webview
反之,在出现错误时显示覆盖。但是活动指示器覆盖图是一个很好的例子,它表示直到加载完成或遇到错误。
据我所知,除了这些令人失望的方式外,我们无能为力,因为我宁愿不与系统抗争。
编辑:Android的Firefox Focus与快速替换错误处理程序中的内容相同。
这是在Java的源代码中完成的:
和
所以我认为我们在一起很好!
编辑2 :我很好奇,如果在真正的Android设备上未处于调试模式时,此显示是否确实可见。我的有根据的猜测是该代码的执行速度更快,并且根本不可见。顺便说一下,此页面可能仅显示404(未找到)错误,如果您使用硬编码的URL和您自己的服务器,则不太可能出现。
编辑3 :可见本机错误页面 在发布模式下的真实设备上运行。防止这种闪烁的唯一方法是创建一个覆盖图。我打开了一个与另一个错误相关的问题,该错误在https://github.com/react-native-community/react-native-webview/issues/474#issuecomment-487022106的react-native-webview
处也解决了。
答案 1 :(得分:1)
我的解决方案是警报功能
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' }} />
);
}
};
答案 2 :(得分:0)
实际上,就我而言,这种解决方案很奏效
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;