202

How do I display a hyperlink in a React Native app?

e.g.

<a href="https://google.com>Google</a> 
biw
  • 3,000
  • 4
  • 23
  • 40
Will Chu
  • 2,073
  • 2
  • 11
  • 6
  • 2
    Consider adding more tags like 'javascript' to get more attention from users. But do not over-generalize your posts by adding tags like 'coding', etc. – Matt C May 29 '15 at 23:07
  • 2
    @MattC I would argue that adding 'javascript' is too general. – ryanwebjackson May 07 '20 at 03:53

14 Answers14

407

Something like this:

<Text style={{color: 'blue'}}
      onPress={() => Linking.openURL('http://google.com')}>
  Google
</Text>

using the Linking module that's bundled with React Native.

import { Linking } from 'react-native';
Pavel Chuchuva
  • 22,633
  • 10
  • 99
  • 115
33

The selected answer refers only to iOS. For both platforms, you can use the following component:

import React, { Component, PropTypes } from 'react';
import {
  Linking,
  Text,
  StyleSheet
} from 'react-native';

export default class HyperLink extends Component {

  constructor(){
      super();
      this._goToURL = this._goToURL.bind(this);
  }

  static propTypes = {
    url: PropTypes.string.isRequired,
    title: PropTypes.string.isRequired,
  }

  render() {

    const { title} = this.props;

    return(
      <Text style={styles.title} onPress={this._goToURL}>
        >  {title}
      </Text>
    );
  }

  _goToURL() {
    const { url } = this.props;
    Linking.canOpenURL(url).then(supported => {
      if (supported) {
        Linking.openURL(this.props.url);
      } else {
        console.log('Don\'t know how to open URI: ' + this.props.url);
      }
    });
  }
}

const styles = StyleSheet.create({
  title: {
    color: '#acacac',
    fontWeight: 'bold'
  }
});
David Schumann
  • 13,380
  • 9
  • 75
  • 96
Kuf
  • 17,318
  • 6
  • 67
  • 91
  • 3
    The selected answer worked fine for me in Android (RN 35). – Pedram Jan 19 '17 at 21:23
  • 3
    @JacobLauritzen well now it's the same after someone copied my answer :/ http://stackoverflow.com/posts/30540502/revisions – Kuf Mar 31 '17 at 14:10
  • Not in all cases suppoted === true, but link is valid. This is my approach to open link for both platfom https://stackoverflow.com/a/69089232/8602069 – Slava Vasylenko Sep 07 '21 at 14:58
32

To do this, I would strongly consider wrapping a Text component in a TouchableOpacity. When a TouchableOpacity is touched, it fades (becomes less opaque). This gives the user immediate feedback when touching the text and provides for an improved user experience.

You can use the onPress property on the TouchableOpacity to make the link happen:

<TouchableOpacity onPress={() => Linking.openURL('http://google.com')}>
  <Text style={{color: 'blue'}}>
    Google
  </Text>
</TouchableOpacity>
David Schumann
  • 13,380
  • 9
  • 75
  • 96
Tom Aranda
  • 5,919
  • 11
  • 35
  • 51
21

React Native documentation suggests using Linking:

Reference

Here is a very basic use case:

import { Linking } from 'react-native';

const url="https://google.com"

<Text onPress={() => Linking.openURL(url)}>
    {url}
</Text>

You can use either functional or class component notation, dealers choice.

jasonleonhard
  • 12,047
  • 89
  • 66
9

Another helpful note to add to the above responses is to add some flexbox styling. This will keep the text on one line and will make sure the text doesn't overlap the screen.

 <View style={{ display: "flex", flexDirection: "row", flex: 1, flexWrap: 'wrap', margin: 10 }}>
  <Text>Add your </Text>
  <TouchableOpacity>
    <Text style={{ color: 'blue' }} onpress={() => Linking.openURL('https://www.google.com')} >
         link
    </Text>
   </TouchableOpacity>
   <Text>here.
   </Text>
 </View>
Stephanieraymos
  • 186
  • 1
  • 8
5

Use React Native Hyperlink (Native <A> tag):

Install:

npm i react-native-a

import:

import A from 'react-native-a'

Usage:

  1. <A>Example.com</A>
  2. <A href="example.com">Example</A>
  3. <A href="https://example.com">Example</A>
  4. <A href="example.com" style={{fontWeight: 'bold'}}>Example</A>
fedorqui
  • 275,237
  • 103
  • 548
  • 598
Khalil Laleh
  • 1,168
  • 10
  • 19
3

for the React Native, there is library to open Hyperlinks in App. https://www.npmjs.com/package/react-native-hyperlink

In addition to this, i suppose you will need to check url and best approach is Regex. https://www.npmjs.com/package/url-regex

rajaishwary
  • 4,362
  • 2
  • 14
  • 14
  • If you are building for ios, the SVC is better approach to implement rather than Linking (to open in Safari Browser). https://github.com/naoufal/react-native-safari-view – rajaishwary Nov 18 '16 at 08:35
  • Thanks for sharing https://www.npmjs.com/package/react-native-hyperlink. Do not trouble yourself with all that self written stuff when you can just go for {//text mixed with links} / – tomwaitforitmy Nov 13 '21 at 17:59
3

Here's how to implement a hyperlink that appears underlined and has the web-standard behavior of changing colors when clicked (like CSS a:active).

import { Linking, Pressable, Text } from 'react-native';

  <Pressable onPress={() => Linking.openURL('https://example.com')}>
    {({ pressed }) =>
      <Text style={{
        textDecorationLine: 'underline',
        color: pressed ? 'red' : 'blue'
      }}>I'm a hyperlink!</Text>
    }
  </Pressable>
  • Some of the existing answers use Text and Linking with TouchableOpacity, but the docs state that Pressable is more "future-proof" than TouchableOpacity, so we use Pressable instead.
  • Text itself actually has an onPress() property, so TouchableOpacity is unnecessary for simply handling the press. However, it doesn't seem possible to implement the color style change with Text only.
jrc
  • 20,354
  • 10
  • 69
  • 64
2

Just thought I'd share my hacky solution with anyone who's discovering this problem now with embedded links within a string. It attempts to inline the links by rendering it dynamically with what ever string is fed into it.

Please feel free to tweak it to your needs. It's working for our purposes as such:

This is an example of how https://google.com would appear.

View it on Gist:

https://gist.github.com/Friendly-Robot/b4fa8501238b1118caaa908b08eb49e2

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

export default function renderHyperlinkedText(string, baseStyles = {}, linkStyles = {}, openLink) {
  if (typeof string !== 'string') return null;
  const httpRegex = /http/g;
  const wwwRegex = /www/g;
  const comRegex = /.com/g;
  const httpType = httpRegex.test(string);
  const wwwType = wwwRegex.test(string);
  const comIndices = getMatchedIndices(comRegex, string);
  if ((httpType || wwwType) && comIndices.length) {
    // Reset these regex indices because `comRegex` throws it off at its completion. 
    httpRegex.lastIndex = 0;
    wwwRegex.lastIndex = 0;
    const httpIndices = httpType ? 
      getMatchedIndices(httpRegex, string) : getMatchedIndices(wwwRegex, string);
    if (httpIndices.length === comIndices.length) {
      const result = [];
      let noLinkString = string.substring(0, httpIndices[0] || string.length);
      result.push(<Text key={noLinkString} style={baseStyles}>{ noLinkString }</Text>);
      for (let i = 0; i < httpIndices.length; i += 1) {
        const linkString = string.substring(httpIndices[i], comIndices[i] + 4);
        result.push(
          <Text
            key={linkString}
            style={[baseStyles, linkStyles]}
            onPress={openLink ? () => openLink(linkString) : () => Linking.openURL(linkString)}
          >
            { linkString }
          </Text>
        );
        noLinkString = string.substring(comIndices[i] + 4, httpIndices[i + 1] || string.length);
        if (noLinkString) {
          result.push(
            <Text key={noLinkString} style={baseStyles}>
              { noLinkString }
            </Text>
          );
        }
      }
      // Make sure the parent `<View>` container has a style of `flexWrap: 'wrap'`
      return result;
    }
  }
  return <Text style={baseStyles}>{ string }</Text>;
}

function getMatchedIndices(regex, text) {
  const result = [];
  let match;
  do {
    match = regex.exec(text);
    if (match) result.push(match.index);
  } while (match);
  return result;
}
Friendly-Robot
  • 1,124
  • 14
  • 24
2

Import Linking the module from React Native

import { TouchableOpacity, Linking } from "react-native";

Try it:-

<TouchableOpacity onPress={() => Linking.openURL('http://Facebook.com')}>
     <Text> Facebook </Text>     
</TouchableOpacity>
Parveen Chauhan
  • 1,396
  • 12
  • 25
1

<TouchableOpacity onPress={()=>Linking.openURL('http://yahoo.com')}> <Text style={{textDecorationLine:'underline',color:'blue}}>https://google.com

the above code will make your text look like hyperlink

Ruban Dharmaraj
  • 985
  • 1
  • 8
  • 11
0

If you want to do links and other types of rich text, a more comprehensive solution is to use React Native HTMLView.

John Slegers
  • 45,213
  • 22
  • 199
  • 169
Eliot
  • 5,450
  • 3
  • 32
  • 30
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/13192218) – Ari0nhh Aug 02 '16 at 04:47
  • @Ari0nhh I undeleted the question as it was the only way I could respond to your comment. There's lots of precedents on SO where a highly ranked answer is simply a link to a good library. Plus other answers already cover a simple implementation. I suppose I could repost this as a comment on the original question, but I do view it as a real answer. And leaving the link here is at least a crumb for future seekers, if people want to edit it and improve it with better examples at least now there's a place to start. – Eliot Aug 02 '16 at 21:05
0

You can use linking property <Text style={{color: 'skyblue'}} onPress={() => Linking.openURL('http://yahoo.com')}> Yahoo

0

I was able to use the following to align the touchable substring with the surrounding text. The fixed margin numbers are a bit hacky, but good enough if you don't need to use this with more than one font size. Otherwise you can pass the margins in as a prop along with the BaseText component.

import styled, { StyledComponent } from 'styled-components'
import { View, Linking, Text, TouchableOpacity } from 'react-native'

type StyledTextComponent = StyledComponent<typeof Text, any, {}, never>

export interface TouchableSubstringProps {
  prefix: string
  substring: string
  suffix: string
  BaseText: StyledTextComponent
  onPress: () => void
}

export const TouchableSubstring = ({
  prefix,
  substring,
  suffix,
  BaseText,
  onPress,
}: TouchableSubstringProps): JSX.Element => {
  const UnderlinedText = styled(BaseText)`
    text-decoration: underline;
    color: blue;
  `

  return (
    <TextContainer>
      <Text>
        <BaseText>{prefix}</BaseText>
        <TextAlignedTouchableOpacity onPress={onPress}>
          <UnderlinedText>{substring}</UnderlinedText>
        </TextAlignedTouchableOpacity>
        <BaseText>{suffix}</BaseText>
      </Text>
    </TextContainer>
  )
}

const TextContainer = styled(View)`
  display: flex;
  flex: 1;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 10px;
`

const TextAlignedTouchableOpacity = styled(TouchableOpacity)`
  margin-top: 1px;
  margin-bottom: -3px;
`

blwinters
  • 1,911
  • 19
  • 40