2
votes

Supprimer la page d'erreur par défaut d'Android sur la vue Web native de réaction

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: entrez la description de l'image ici 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.


2 commentaires

Avez-vous trouvé une solution à cela? J'ai le même problème


Non, je n'ai pas encore trouvé de solution valable :(


3 Réponses :


1
votes

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:

https://github.com/mozilla-mobile/focus-android/blob/c789362b9c331b2036755a8398e3770be43b50b8/app/src/main/java/org/mozilla/focus/webview/Focus /#30WebViewClient3 a>

et

https://github.com/mozilla-mobile/focus-android/blob/63339d2d9a5d132bf4a1fffc4c46c0ce393abe87/app/src/main/java/org/mozilla/focusava/webview/ErrorPage12 a>.

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>


2 commentaires

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.



2
votes

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' }} />
    );
  }
};

entrez la description de l'image ici


0 commentaires

0
votes

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;


0 commentaires