react-native-webview: onNavigationStateChange: Unable to prevent navigation on android, working on iOS

Bug description:

I’m trying to intercept a navigation change. On iOS, this works correctly where ref.current.stopLoading() prevents the WebView from navigating. On Android, it goes ahead and navigates (if at least partially) before stopLoading() takes effect.

To Reproduce:

I’ve made a fresh repo that exhibits this behaviour: https://github.com/alancwoo/react-native-webview-iss-1625

const App: () => React$Node = () => {
  const [url, setUrl] = useState('https://github.com/react-native-community/react-native-webview')
  const [key, setKey] = useState(0)

  const webViewRef = useRef(null)
  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView style={{ flex: 1, width: '100%' }}>
        <WebView
          key={key}
          ref={webViewRef}
          source={{ uri: url }}
          style={{ flex: 1, width: '100%' }}
          onNavigationStateChange={(event) => {
            if (event.url !== url) {
              webViewRef.current.stopLoading()
              Alert.alert('stopped')
            }
          }}
        />
      </SafeAreaView>
    </>
  );
};

Expected behavior:

Android should behave the same as on iOS, and should halt loading before transitioning.

Screenshots/Videos:

Android Start: image

Tap on ‘Sign Up’ (Loads signup page before stopping and showing alert): image

iOS (Correctly stops loading and shows alert): image

Environment:

  • OS: Mac OS
  • OS version: 10.15.6
  • react-native version: 0.63.2
  • react-native-webview version: ^10.8.3

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 9
  • Comments: 28

Most upvoted comments

work with me

onLoadProgress={(e) => {
          const state = e.nativeEvent;
          setCanGoBack(state.canGoBack)
}}

Screenshot (168)

@alancwoo

react-native-webview: ^11.2.1 react-native: 0.63.4

I tried using onShouldStartLoadWithRequest didn’t work 😕. No matter what, the page always redirects. The issue is only on Android. iOS works as expected.

After updating: react-native-webview: 10.8.3 > 11.0.2 react-native: 0.6.2 > 0.6.4

I can confirm that on android, onShouldStartLoadWithRequest is behaving correctly now:

      <SafeAreaView style={{ flex: 1, width: '100%' }}>
        <WebView
          key={key}
          ref={webViewRef}
          source={{ uri: url }}
          style={{ flex: 1, width: '100%' }}
          onShouldStartLoadWithRequest={(event) => {
            if (event.url !== url) {
              // webViewRef.current.stopLoading()
              Alert.alert('Prevent loading')
              return false
            } else {
              return true
            }
          }}
        />
      </SafeAreaView>

Still searching for solutions

I find onLoadProgress callback function has the very simillar paramters like onNavigationStateChange.

I’ve called onLoadProgress instead of calling onNavigationStateChange.

Why can’t you use onShouldStartLoadWithRequest?

Be carefull with Next.js Link component. It will not trigger onShouldStartLoadWithRequest. It needs to be an <a>.

I see the banner now that you point it out. Before I think I CTRL-F’d right by it. With the new docs/code showing full cross platform compatibility, I can’t imagine a reason this bug would need to stay open. Anyhow, just wanted to mention your solution worked for me, so I would encourage the others who stumble on this page to follow it. Also I like the newer docs. Better sample to be had there.

Thanks for sharing.

@TheAlmightyBob That worked for me. Thanks. I’m using a physical Android v9 phone. A $20 disposable quality phone, so not really special hardware…

Also I noticed the URL https://reactnative.dev/docs/webview indicates a platform of iOS. Perhaps it’s not consistently supported on Android…? Maybe this is what others are seeing?

<WebView onShouldStartLoadWithRequest={(req) => { if ("https://myspecialUrl" == req.url) { return false; } return true; }} />

@ausshadu @swathi2378 Same question as above, why can’t you use onShouldStartLoadWithRequest?

Any updates on this? Facing the exact same issue.