What is the proper way to replace urls in a string and render them as links with React?
Say I have a string: 'hello http://google.com world'
, and I want it to render like: hello <a href="http://google.com">http://google.com</a> world
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>
)
}
}
There are NPM modules to handle this. Both of these depend on linkify-it (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.
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>
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 + " "
);
Try this library, it does exactly you need: https://www.npmjs.com/package/react-process-string
An example from there:
const processString = require('react-process-string');
let config = [{
regex: /(http|https):\/\/(\S+)\.([a-z]{2,}?)(.*?)( |\,|$|\.)/gim,
fn: (key, result) => <span key={key}>
<a target="_blank" href={`${result[1]}://${result[2]}.${result[3]}${result[4]}`}>{result[2]}.{result[3]}{result[4]}</a>{result[5]}
</span>
}, {
regex: /(\S+)\.([a-z]{2,}?)(.*?)( |\,|$|\.)/gim,
fn: (key, result) => <span key={key}>
<a target="_blank" href={`http://${result[1]}.${result[2]}${result[3]}`}>{result[1]}.{result[2]}{result[3]}</a>{result[4]}
</span>
}];
let stringWithLinks = "Watch this on youtube.com";
let processed = processString(config)(stringWithLinks);
return (
<div>Hello world! {processed}</div>
);
That will replace all links with or without "http://" protocol. If you want to replace only links with protocol, remove the second object from config array.
First add <a>
tag to string:
function httpHtml(content) {
const reg = /(http:\/\/|https:\/\/)((\w|=|\?|\.|\/|&|-)+)/g;
return content.replace(reg, "<a href='$1$2'>$1$2</a>");
}
console.log(httpHtml('hello http://google.com world'))
// => hello <a href="http://google.com">http://google.com</a> world
Then render string as html in react:
function MyComponent() {
return <div dangerouslySetInnerHTML={{
__html: httpHtml('hello http://google.com world')
}} />;
}
I wrote a short function to do it:
const RE_URL = /\w+:\/\/\S+/g;
function linkify(str) {
let match;
const results = [];
let lastIndex = 0;
while (match = RE_URL.exec(str)) {
const link = match[0];
if (lastIndex !== match.index) {
const text = str.substring(lastIndex, match.index);
results.push(
<span key={results.length}>{text}</span>,
);
}
results.push(
<a key={results.length} href={link} target="_blank">{link}</a>
);
lastIndex = match.index + link.length;
}
if (results.length === 0) {
return str;
}
if (lastIndex !== str.length) {
results.push(
<span key={results.length}>{str.substring(lastIndex)}</span>,
);
}
return results;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With