0

I am trying to create a dynamic link Component that transforms a string in a string with a html anchor.

What I want to obtain is a component that returns this output:

<p>Do you want <a href="http://google.com">to search</a>?</p>

I am passing this object to the component

let phrase = {
  text :  'Do you want to search?'
  linktext : 'to search',
  linkurl  : 'http://google.com'
}

This is the component I tried but do not work and the html is rendered as a text

function InfoLink(props) {
  const q = props.phrase;
  const link = "<a href={q.linkurl} >{q.linktext}</a>";
  const text = q.text.replace(q.linktext, link);
  return (
    <p>{text}</p>
  );
}

Is there a way to have a html output from the component by using replace?

fruxz
  • 23
  • 3
  • 2
    https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml – zero298 Feb 27 '20 at 16:36
  • Does this answer your question? [Rendering raw html with reactjs](https://stackoverflow.com/questions/27934238/rendering-raw-html-with-reactjs) – Wiktor Zychla Feb 27 '20 at 16:39
  • 2
    The best solution would be to create another component that takes `linkurl` and `linktext` as `props` and returns `{linktext}`. You could technically do `const link = () => ({q.linktext}))` but the first approach is preferred. Also, stay away from using `dangerouslySetInnerHTML` unless **you know what you're doing**. – goto Feb 27 '20 at 16:40
  • well I would like to avoid using dangerouslySetInnerHTML in favour of more elegant solutions – fruxz Feb 28 '20 at 11:42

3 Answers3

1

You can split the text, and output the split text along with a react component for the anchor:

let phrase = {
  text :  'Do you want to search?',
  linktext : 'to search',
  linkurl  : 'http://google.com'
}

function InfoLink(props) {
  const q = props.phrase;
  const link = <a href={q.linkurl}>{q.linktext}</a>;
  const [part1, part2] = q.text.split(q.linktext);
  return (
    <p>{part1}{link}{part2}</p>
  );
}

ReactDOM.render(<InfoLink phrase={phrase}/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
KevBot
  • 17,900
  • 5
  • 50
  • 68
  • Thanks that is a very nice way to solve the problem!, at the end I came up with the three pieces split as well, but your code is much more elegant and easy to read! – fruxz Feb 28 '20 at 11:52
0

You can split your sentence in 3 parts:

text_before_link <a href={q.linkurl}> text_with_link </a> text_after_link

Where...

text_before_link = q.text.substr(0,q.text.indexOf(q.linktext));
text_with_link = q.linktext;
text_after_link = q.text.substr(q.text.indexOf(q.linktext)+q.linktext.length);

Something like that.

0

The variable link is a JSX Object and you are adding it to an string. So the result will be something like: Do you want [Object][Object]. To solve this problem, you should split the string you want to show and the object and return both.

export default function App (props){
const q = props.phrase;
const link = <a href={q.linkurl}>{q.linktext}</a>;
const text = q.text.split(q.linktext)[0];
return (
    <p>{text}{link}</p>
);}

Hope this can help.

FaSh
  • 99
  • 8