The way I ended up doing this is perhaps not the most efficient way, but it does work. I split the string up into its component words with
str.split(" ")
Then iterated through the created array to check whether a word started with #
, @
, or a link.
function compose(post) {
let str = "";
let blnFlag = false;
let arrWords = [];
let arrJSX = [];
let array = post.split(/\s/);
for (let word of array) {
if (/^#.+/i.test(word)) { arrWords.push( {text: word, type: "tag"} ); }
else if (/^@.+/i.test(word)) { arrWords.push( {text: word, type: "mention"} ); }
else if (/^(http|www).+/i.test(word)) { arrWords.push( {text: word, type: "link"} );}
else { arrWords.push( {text: word, type: "plain"} ); }
}
for (let word of arrWords) {
if (word.type === "plain") {
str += word.text + " ";
} else {
blnFlag = true;
if(str) {
arrJSX.push(<Text>{str}</Text>);
str = "";
}
switch(word.type) {
case "tag":
arrJSX.push(<Text style={styles.tags_mentions_links}>{word.text + " "}</Text>);
break;
case "mention":
arrJSX.push(<Text style={styles.tags_mentions_links}>{word.text + " "}</Text>);
break;
case "link":
arrJSX.push(<Text style={styles.tags_mentions_links} onPress={() => {Linking.openURL(word.text)}}>{word.text + " "}</Text>);
break;
}
}
}
if(!blnFlag) {
arrJSX.push(<Text>{str}</Text>);
}
return arrJSX;
}
Returning an array of JSX to the parent component allows you to map
the array and output JSX directly
function Child(props) {
let arrJSX = Util.compose(props.info.body);
return (<P text=
{arrJSX.map((jsx, index) => {
return(<Text key={index}>{jsx}</Text>)
})}
/>)
}