проблема с встроенной навигацией webview на аппаратном уровне

#react-native #react-native-android #react-native-webview

#react-native #react-native-android #react-native-webview

Вопрос:

Я открываю URL-адрес в webview. При открытии webview (скажем, страница A), когда я просматриваю или захожу в любые другие параметры, нажимая некоторые параметры, открывается какая-то другая страница (скажем, страница B). Теперь, когда я нажимаю на опцию аппаратного обеспечения, я хочу вернуться к предыдущим экранам, то есть (страница A). И снова, щелкнув назад, я хочу вернуться в свое приложение.

Пробовал следующее,

 const [canGoBack, setCanGoBack] = useState(false);
const WebViewRef = useRef<WebView>(null);

useEffect(() => {
  if (Platform.OS === "android") {
    BackHandler.addEventListener("hardwareBackPress", HandleBackPressed);

    return () => {
      BackHandler.removeEventListener("hardwareBackPress", HandleBackPressed);
    };
  }
}, []);

<WebView
  ref={WebViewRef}
  // onLoadStart={() => setLoading!(true)}
  onLoadEnd={() => setLoading!(false)}
  source={{ uri: props.navigation.getParam("x") }}
  onNavigationStateChange={(data) => handleResponse(data, WebViewRef)}
/>;

const handleResponse = (data: NavState, WebViewRef: any) => {
  console.log(data.canGoBack); // <- always false, if i can go back further back or not in a webview
  setCanGoBack(data?.canGoBack!);
};

const HandleBackPressed = () => {
  if (WebViewRef.current amp;amp; canGoBack) {
    WebViewRef.current.goBack();
    return true; // PREVENT DEFAULT BEHAVIOUR (EXITING THE APP)
  }
  return false;
};
 

Как этого добиться?

Комментарии:

1. в чем проблема с вашим подходом?

Ответ №1:

В вашем коде canGoBack обновления не отражаются в методе backHandler, поскольку useEffect запускается только при инициализации.

Вы можете сделать так, чтобы этот эффект зависел от canGoBack следующим образом:

   React.useEffect(() => {
    if (Platform.OS === 'android') {
      const backHandler = BackHandler.addEventListener(
        'hardwareBackPress',
        () => {
          if (webViewRef.current amp;amp; canGoBack) {
            webViewRef.current.goBack();
            return true; // PREVENT DEFAULT BEHAVIOUR (EXITING THE APP)
          }
          return false;
        }
      );

      return () => backHandler.remove();
    }
  }, [canGoBack]);
 

Вы можете увидеть рабочий пример закуски здесь: https://snack.expo.io/QcYE9CTaO

Было бы немного чище, если бы вы могли обернуть метод backHandler в useCallback so, который зависит от значения состояния, а затем useEffect, который зависит от new backHandler .