J'utilise une vue Web dans React native et je souhaite afficher un message d'erreur personnalisé en cas d'erreur (par exemple, pas de connexion Internet).
Mon code:
<WebView renderError={() => ( <MissingConnection /> )} other params.... />
Lorsqu'une erreur se produit lors du chargement de la page Web, pendant une fraction de seconde, la vue Web affiche l'erreur Android par défaut, telle que:
puis mon composant MissingConnection
apparaît, cachant la vue Web.
Existe-t-il un moyen de supprimer complètement l'écran d'erreur Android par défaut? Il clignote pendant juste une fraction de seconde et le résultat semble vraiment faux.
3 Réponses :
Tout d'abord: Vous faites les choses correctement .
J'ai observé le même problème récemment et j'ai fait quelques recherches. Le problème ne réside pas dans votre code ou React Native ou react-native-webview
.
Il ne s'agit que du comportement par défaut de la WebView
d'Android. De nombreux développeurs Java rencontrent le même problème, des exemples de threads associés sur SO:
erreur d'affichage Web lors du chargement d'une page sans Internet < / a>
Empêcher WebView d'afficher "page Web non disponible "
Android WebView onReceivedError ()
Les propositions habituelles pour contourner sont:
vérifier la connexion Internet avant d'essayer de charger quoi que ce soit (éviter les échecs)
supprimez rapidement le contenu de l'erreur et affichez votre propre contenu dans onReceivedError
(qui correspond essentiellement à votre méthode renderError
dans react-native-webview
). Parfois, avec le chargement d'une URL locale comme cela est fait en Java ici . < / p>
veillez à avoir une superposition qui est supprimée au cas où il n'y aurait aucune erreur. react-native-webview
fait l'inverse, affichant une superposition en cas d'erreur. Mais la superposition d'indicateur d'activité est un bon exemple, elle indique jusqu'à ce que le chargement soit terminé ou rencontre une erreur.
Autant que je sache, nous ne pouvons rien faire d'autre que ces moyens décevants, car je préférerais ne pas lutter contre le système.
Modifier : Firefox Focus pour Android fait de même en remplaçant rapidement le contenu dans le gestionnaire d'erreurs.
C'est fait en Java dans leur source ici:
et
Je suppose donc que nous sommes en bonne compagnie!
Modifier 2 : je suis curieux de savoir si cela est vraiment visible lorsque vous n'êtes pas en mode débogage sur un vrai appareil Android. Ma supposition éclairée est que le code s'exécute beaucoup plus rapidement et qu'il ne devrait pas être visible du tout. Btw cette page n'est probablement affichée que pour les erreurs 404 (non trouvées) qui sont peu probables si vous utilisez des URL codées en dur et vos propres serveurs.
Modifier 3 : la page d'erreur native est visible en cours d'exécution sur un appareil réel en mode version. La seule façon d'éviter ce scintillement serait de créer une superposition. J'ai ouvert un problème lié à une autre erreur qui corrige également celle-ci avec react-native-webview
ici https://github.com/react-native-community/react-native-webview/issues/474#issuecomment-487022106 . < / p>
Bonne réponse. Je vais faire quelques tests sur une apk compilée juste par curiosité
@gbalduzzi De rien! J'ai observé la même chose récemment, donc je suis aussi curieuse. L'approche avec une autre superposition semble être trop lourde, du moins pour mon projet actuel.
Mes solutions sont la fonction d'alerte
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' }} /> ); } };
En fait, dans mon cas, cette solution a fonctionné bien
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;
Avez-vous trouvé une solution à cela? J'ai le même problème
Non, je n'ai pas encore trouvé de solution valable :(