React: replace links in a text

There are NPM modules to handle this. Both of these depend on linkify-it (repo)

react-linkify (repo)

<Linkify>
  <div>react-linkify <span>(tasti.github.io/react-linkify/)</span></div>
    <div>React component to parse links (urls, emails, etc.) in text into clickable links</div>
  See examples at tasti.github.io/react-linkify/.
    <footer>Contact: [email protected]</footer>
</Linkify>

At time of writing, the current version is 1.0.0-alpha. It requires React 16. The repo has 14 open tickets and 17 open PRs. So that's not fantastic.

Version 0.2.2 allows much earlier versions but doesn't have link text decoration, etc.

react-native-hyperlink ( repo )

If you are using native (ie a phone app), it looks like the better of the two options. Code samples:

<Hyperlink linkDefault={ true }>
  <Text style={ { fontSize: 15 } }>
    This text will be parsed to check for clickable strings like https://github.com/obipawan/hyperlink and made clickable.
  </Text>
</Hyperlink>

<Hyperlink onLongPress={ (url, text) => alert(url + ", " + text) }>
  <Text style={ { fontSize: 15 } }>
    This text will be parsed to check for clickable strings like https://github.com/obipawan/hyperlink and made clickable for long click.
  </Text>
</Hyperlink>

<Hyperlink
  linkDefault
  injectViewProps={ url => ({
        testID: url === 'http://link.com' ? 'id1' : 'id2' ,
        style: url === 'https://link.com' ? { color: 'red' } : { color: 'blue' },
        //any other props you wish to pass to the component
  }) }
>
  <Text>You can pass props to clickable components matched by url.
    <Text>This url looks red https://link.com
  </Text> and this url looks blue https://link2.com </Text>
</Hyperlink>

References

  • https://github.com/facebook/react-native/issues/3148
  • REACT - How to replace URL strings to <a> elements and rendering it properly

I ran into issues with every answer here, so I had to write my own:

// use whatever you want here
const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;

const renderText = txt =>
  txt
    .split(" ")
    .map(part =>
      URL_REGEX.test(part) ? <a href={part}>{part} </a> : part + " "
    );

Ok, so this is how I done it.

class A extends React.Component {
  renderText() {
    let parts = this.props.text.split(re) // re is a matching regular expression
    for (let i = 1; i < parts.length; i += 2) {
      parts[i] = <a key={'link' + i} href={parts[i]}>{parts[i]}</a>
    }
    return parts
  }
  render() {
    let text = this.renderText()
    return (
      <div className="some_text_class">{text}</div>
    )
  }
}