React Native - open links in browser

Hi i am using react native's webview to display some html, i want that whenever a user clicks a link inside that html, it will open the user's browser with that link.

is that possible?

Edit 1:

I ended up using this package : npmjs.com/package/react-native-communications which opens the browser. I call the browser to open on onNavigationStateChange when the URL changes.

The thing now is that the WebView still continues to process the request although I have moved to the browser, how can i stop the request?


Solution 1:

Here is a complete working solution:

import React, { Component } from 'react';
import { WebView, Linking } from 'react-native';

export default class WebViewThatOpensLinksInNavigator extends Component {
  render() {
    const uri = 'http://stackoverflow.com/questions/35531679/react-native-open-links-in-browser';
    return (
      <WebView
        ref={(ref) => { this.webview = ref; }}
        source={{ uri }}
        onNavigationStateChange={(event) => {
          if (event.url !== uri) {
            this.webview.stopLoading();
            Linking.openURL(event.url);
          }
        }}
      />
    );
  }
}

It uses a simple WebView, intercepts any url change, and if that url differs from the original one, stops the loading, preventing page change, and opens it in the OS Navigator instead.

ios simulator

Solution 2:

A big issue with using "stopLoading()" is that on Android it disables further taps on any other links from that source page.

The WebView component is being split out of core RN and into the community's hands. If you use that version instead (https://github.com/react-native-community/react-native-webview), you can use "onShouldStartLoadWithRequest" prop on both iOS and Android, which makes this a lot more elegant.

Building off of Damien Varron's really helpful answer, here's an example for how you'd leverage that prop to avoid stopLoading that works cross platform:

onShouldStartLoadWithRequest={event => {
    if (event.url !== uri) {
        Linking.openURL(event.url)
        return false
    }
    return true
}}

And here's how you might do it if your source is HTML as opposed to a URI:

onShouldStartLoadWithRequest={event => {
    if (event.url.slice(0,4) === 'http') {
        Linking.openURL(event.url)
        return false
    }
    return true
}}

As basbase pointed out, you could also do it this way (I've added the about:blank part). I plan to trial and error more to see which holds up best.

onShouldStartLoadWithRequest={event => {
    if (!/^[data:text, about:blank]/.test(event.url)) {
        Linking.openURL(event.url)
        return false
    }
    return true
}}

Solution 3:

Linking.openURL(url).catch(err => console.error('An error occurred', err));

https://facebook.github.io/react-native/docs/linking.html