Mcestone
Mcestone

Reputation: 864

Render string containing JSX in react binding

I've found a lot of questions that are similar to this but none that actually answer my question.

I have a string that contains a JSX template to create a link and need to render this in the binding within a Text component. Below I have some same text so you can see approximately what I have.

Currently {content} will render as This string has JSX: [Object, object]. How do I make it actually render FAQLink.

What I've tried

I've tried using <React.Fragment>{content}<React.Fragment> with no luck.

function TooltipContent() {
 const FAQLink = () => (
  <Link
    color="teal40"
    hoverColor="teal30"
    underlined
    to={paths.resourcePage({ slug: 'frequently-asked-questions' })}
  >
    FAQ
  </Link>
 );

 const contentArray = [
  `This string has JSX: ${<FAQLink />}`,
  `Another possible string`
 ];

 let content;
 if (variant === 'risk') {
  content = contentArray[0];
 } else {
  content = contentArray[1];
 }

 return (
  <Text textAlign="left" p={2}>
    {content}
  </Text>
 );
}

This code does work but isn't possible for my case

function TooltipContent() {
 const FAQLink = () => (
  <Link
    color="teal40"
    hoverColor="teal30"
    underlined
    to={paths.resourcePage({ slug: 'frequently-asked-questions' })}
  >
    FAQ
  </Link>
 );

 return (
  <Text textAlign="left" p={2}>
    This string has JSX: <FAQLink />
  </Text>
 );
}

Upvotes: 1

Views: 426

Answers (3)

Antonio Giordano
Antonio Giordano

Reputation: 173

Remember that JSX is just sugar syntax for React functions. Your code transpiles like this:

"use strict";

function TooltipContent() {
  var FAQLink = function FAQLink() {
    return React.createElement(Link, {
      color: "teal40",
      hoverColor: "teal30",
      underlined: true,
      to: paths.resourcePage({
        slug: 'frequently-asked-questions'
      })
    }, "FAQ");
  };

  var content = "This string has JSX: ".concat(React.createElement(FAQLink, null));
  return React.createElement(Text, {
    textAlign: "left",
    p: 2
  }, content);
}

So that concat function, or the ${} syntax, just converts your React elements (that is an object) into a string, but this results in [Object object].

What you are trying to do, in this way, will always give you this result. Can you explain why you have to do this and you can not do in the other way?

Upvotes: 0

goto
goto

Reputation: 4445

Unfortunately, template literals won't work with React components.

However, you could utilize React.Fragment to accomplish what you need, like in the following example:

function TooltipContent(props) {
  const { variant = "default" } = props;
  const FAQLink = () => <a href="https://google.com">I am a link!</a>;

  let content;

  switch (variant) {
    case "risk":
      content = (
        <React.Fragment>
          RISK! <br />
          <FAQLink />
        </React.Fragment>
      );
      break;
    case "no-risk":
      content = "NO RISK";
      break;
    default:
      content = variant;
  }
  return <p>{content}</p>;
}

Here's a working example:

Upvotes: 1

Vitaly Yastremsky
Vitaly Yastremsky

Reputation: 386

If I understand correctly, you wants to render FAQLink as a code example, If yes here is code example: https://codesandbox.io/s/render-jsx-text-u480p?fontsize=14&hidenavigation=1&theme=dark

Upvotes: 0

Related Questions