ketan
ketan

Reputation: 19341

Display styled text in react styled pre component

I am trying to highlight some text in React pre. But, it doesn't seems working. It shows [object Object] instead of text.

const Text = styled.pre `
    color: black;
    padding-bottom: 10px;
`;

const HighLight = styled.span `
    color: red;
`;



let obj = [{
  id: 123,
  name: 'abcd',
}, {
  id: 234,
  name: 'new name',
}];

let str = "[123] Hello how are you? [234] and you? [123] Please call me.";

obj.forEach(o => {
      str = str.replace(new RegExp('\\[' + o.id + '\\]', 'gi'), <HighLight>{o.name}</HighLight>);
      });

    console.log(str);


    render() {
      return ( <Text> {str}</Text>);
      }
<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>

Also I tried following but, same result

const Text = styled.span `
        color: black;
        padding-bottom: 10px;
    `;

<Text dangerouslySetInnerHTML={{ __html: str }} />

Any help would be greatly appreciated.

Upvotes: 0

Views: 217

Answers (1)

Felix Kling
Felix Kling

Reputation: 816810

As I have mentioned in my comment, you cannot insert React elements into a string because React elements are objects. Instead you have to somehow parse the string and create a list of React elements instead.

In your specific example you can get away with using a regular expression to split the string and map every part to either itself (plain string) or a React element, if it matches the pattern. We take advantage of the fact that JavaScript includes the delimiter in the result array if we us

function HighLight({children}) {
  return <strong>{children}</strong>;
}

let obj = [{
  id: 123,
  name: 'abcd',
}, {
  id: 234,
  name: 'new name',
}];

const elements = "[123] Hello how are you? [234] and you? [123] Please call me.".split(/(\[\d+\])/).map(match => {
   if (/\[\d+\]/.test(match)) {
     return (
       <HighLight>
         {obj.find(o => o.id === Number(match.slice(1,-1))).name}
       </HighLight>
     );
   }
   return match;
});

ReactDOM.render(
  elements,
  document.body
);
<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>

Of course if you change your data structure to use the IDs as property names, then getting the right object would be easier.

I would have suggested to use a custom tagged template but I assume that you have no control over the string input.

Upvotes: 2

Related Questions